Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'CPP/7zip/Archive/Nsis/NsisHandler.cpp')
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Nsis/NsisHandler.cpp643
1 files changed, 407 insertions, 236 deletions
diff --git a/CPP/7zip/Archive/Nsis/NsisHandler.cpp b/CPP/7zip/Archive/Nsis/NsisHandler.cpp
index 4058bd2a..868ca6cb 100755..100644
--- a/CPP/7zip/Archive/Nsis/NsisHandler.cpp
+++ b/CPP/7zip/Archive/Nsis/NsisHandler.cpp
@@ -4,11 +4,12 @@
#include "../../../../C/CpuArch.h"
-#include "Common/ComTry.h"
-#include "Common/IntToString.h"
+#include "../../../Common/ComTry.h"
+#include "../../../Common/IntToString.h"
-#include "Windows/PropVariant.h"
+#include "../../../Windows/PropVariant.h"
+#include "../../Common/ProgressUtils.h"
#include "../../Common/StreamUtils.h"
#include "../Common/ItemNameUtils.h"
@@ -27,54 +28,160 @@ static const char *kUnknownMethod = "Unknown";
static const char *kMethods[] =
{
- "Copy",
- "Deflate",
- "BZip2",
- "LZMA"
+ "Copy"
+ , "Deflate"
+ , "BZip2"
+ , "LZMA"
};
-static const int kNumMethods = sizeof(kMethods) / sizeof(kMethods[0]);
-
-static STATPROPSTG kProps[] =
+static const Byte kProps[] =
{
- { NULL, kpidPath, VT_BSTR},
- { NULL, kpidSize, VT_UI8},
- { NULL, kpidPackSize, VT_UI8},
- { NULL, kpidMTime, VT_FILETIME},
- { NULL, kpidMethod, VT_BSTR},
- { NULL, kpidSolid, VT_BOOL}
+ kpidPath,
+ kpidSize,
+ kpidPackSize,
+ kpidMTime,
+ kpidAttrib,
+ kpidMethod,
+ kpidSolid,
+ kpidOffset
};
-static STATPROPSTG kArcProps[] =
+static const Byte kArcProps[] =
{
- { NULL, kpidMethod, VT_BSTR},
- { NULL, kpidSolid, VT_BOOL}
+ kpidMethod,
+ kpidSolid,
+ kpidHeadersSize,
+ kpidEmbeddedStubSize,
+ kpidSubType
+ // kpidCodePage
};
IMP_IInArchive_Props
IMP_IInArchive_ArcProps
+
+static AString UInt32ToString(UInt32 val)
+{
+ char s[16];
+ ConvertUInt32ToString(val, s);
+ return s;
+}
+
+static AString GetStringForSizeValue(UInt32 val)
+{
+ for (int i = 31; i >= 0; i--)
+ if (((UInt32)1 << i) == val)
+ return UInt32ToString(i);
+ char c = 'b';
+ if ((val & ((1 << 20) - 1)) == 0) { val >>= 20; c = 'm'; }
+ else if ((val & ((1 << 10) - 1)) == 0) { val >>= 10; c = 'k'; }
+ return UInt32ToString(val) + c;
+}
+
+static AString GetMethod(bool useFilter, NMethodType::EEnum method, UInt32 dict)
+{
+ AString s;
+ if (useFilter)
+ {
+ s += kBcjMethod;
+ s += ' ';
+ }
+ s += (method < ARRAY_SIZE(kMethods)) ? kMethods[method] : kUnknownMethod;
+ if (method == NMethodType::kLZMA)
+ {
+ s += ':';
+ s += GetStringForSizeValue(dict);
+ }
+ return s;
+}
+
+/*
+AString CHandler::GetMethod(NMethodType::EEnum method, bool useItemFilter, UInt32 dictionary) const
+{
+ AString s;
+ if (_archive.IsSolid && _archive.UseFilter || !_archive.IsSolid && useItemFilter)
+ {
+ s += kBcjMethod;
+ s += ' ';
+ }
+ s += (method < ARRAY_SIZE(kMethods)) ? kMethods[method] : kUnknownMethod;
+ if (method == NMethodType::kLZMA)
+ {
+ s += ':';
+ s += GetStringForSizeValue(_archive.IsSolid ? _archive.DictionarySize: dictionary);
+ }
+ return s;
+}
+*/
+
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{
COM_TRY_BEGIN
- NWindows::NCOM::CPropVariant prop;
- switch(propID)
+ NCOM::CPropVariant prop;
+ switch (propID)
{
- case kpidMethod:
+ // case kpidCodePage: if (_archive.IsUnicode) prop = "UTF-16"; break;
+ case kpidSubType:
{
- UInt32 dict = 1;
- bool filter = false;
- for (int i = 0; i < _archive.Items.Size(); i++)
+ AString s = _archive.GetFormatDescription();
+ if (!_archive.IsInstaller)
{
- const CItem &item = _archive.Items[i];
- filter |= item.UseFilter;
- if (item.DictionarySize > dict)
- dict = item.DictionarySize;
+ if (!s.IsEmpty())
+ s += ' ';
+ s += "(Uninstall)";
}
- prop = GetMethod(filter, dict);
+ if (!s.IsEmpty())
+ prop = s;
break;
}
+
+ case kpidMethod: prop = _methodString; break;
case kpidSolid: prop = _archive.IsSolid; break;
+ case kpidOffset: prop = _archive.StartOffset; break;
+ case kpidPhySize: prop = _archive.ExeStub.Size() + _archive.FirstHeader.ArcSize; break;
+ case kpidEmbeddedStubSize: prop = _archive.ExeStub.Size(); break;
+ case kpidHeadersSize: prop = _archive.FirstHeader.HeaderSize; break;
+
+ case kpidErrorFlags:
+ {
+ UInt32 v = 0;
+ if (!_archive.IsArc) v |= kpv_ErrorFlags_IsNotArc;
+ if (_archive.IsTruncated()) v |= kpv_ErrorFlags_UnexpectedEnd;
+ prop = v;
+ break;
+ }
+
+ case kpidName:
+ {
+ AString s;
+
+ #ifdef NSIS_SCRIPT
+ if (!_archive.Name.IsEmpty())
+ s = _archive.Name;
+ if (!_archive.IsInstaller)
+ {
+ if (!s.IsEmpty())
+ s += '.';
+ s += "Uninstall";
+ }
+ #endif
+
+ if (s.IsEmpty())
+ s = _archive.IsInstaller ? "Install" : "Uninstall";
+ s += (_archive.ExeStub.Size() == 0) ? ".nsis" : ".exe";
+
+ prop = _archive.ConvertToUnicode(s);
+ break;
+ }
+
+ #ifdef NSIS_SCRIPT
+ case kpidShortComment:
+ {
+ if (!_archive.BrandingText.IsEmpty())
+ prop = _archive.ConvertToUnicode(_archive.BrandingText);
+ break;
+ }
+ #endif
}
prop.Detach(value);
return S_OK;
@@ -82,16 +189,26 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
}
-STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 * maxCheckStartPosition, IArchiveOpenCallback * /* openArchiveCallback */)
+STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback * /* openArchiveCallback */)
{
COM_TRY_BEGIN
Close();
{
- if (_archive.Open(
- EXTERNAL_CODECS_VARS
- stream, maxCheckStartPosition) != S_OK)
+ if (_archive.Open(stream, maxCheckStartPosition) != S_OK)
return S_FALSE;
- _inStream = stream;
+ {
+ UInt32 dict = _archive.DictionarySize;
+ if (!_archive.IsSolid)
+ {
+ FOR_VECTOR (i, _archive.Items)
+ {
+ const CItem &item = _archive.Items[i];
+ if (item.DictionarySize > dict)
+ dict = item.DictionarySize;
+ }
+ }
+ _methodString = GetMethod(_archive.UseFilter, _archive.Method, dict);
+ }
}
return S_OK;
COM_TRY_END
@@ -101,7 +218,6 @@ STDMETHODIMP CHandler::Close()
{
_archive.Clear();
_archive.Release();
- _inStream.Release();
return S_OK;
}
@@ -109,74 +225,30 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
{
*numItems = _archive.Items.Size()
#ifdef NSIS_SCRIPT
- + 1
+ + 1 + _archive.LicenseFiles.Size();
#endif
;
return S_OK;
}
-static AString UInt32ToString(UInt32 value)
-{
- char buffer[16];
- ConvertUInt32ToString(value, buffer);
- return buffer;
-}
-
-static AString GetStringForSizeValue(UInt32 value)
-{
- for (int i = 31; i >= 0; i--)
- if (((UInt32)1 << i) == value)
- return UInt32ToString(i);
- char c = 'b';
- if (value % (1 << 20) == 0)
- {
- value >>= 20;
- c = 'm';
- }
- else if (value % (1 << 10) == 0)
- {
- value >>= 10;
- c = 'k';
- }
- return UInt32ToString(value) + c;
-}
-
-AString CHandler::GetMethod(bool useItemFilter, UInt32 dictionary) const
-{
- NMethodType::EEnum methodIndex = _archive.Method;
- AString method;
- if (_archive.IsSolid && _archive.UseFilter || !_archive.IsSolid && useItemFilter)
- {
- method += kBcjMethod;
- method += ' ';
- }
- method += (methodIndex < kNumMethods) ? kMethods[methodIndex] : kUnknownMethod;
- if (methodIndex == NMethodType::kLZMA)
- {
- method += ':';
- method += GetStringForSizeValue(_archive.IsSolid ? _archive.DictionarySize: dictionary);
- }
- return method;
-}
-
-bool CHandler::GetUncompressedSize(int index, UInt32 &size)
+bool CHandler::GetUncompressedSize(unsigned index, UInt32 &size) const
{
size = 0;
const CItem &item = _archive.Items[index];
- if (item.SizeIsDefined)
- size = item.Size;
- else if (_archive.IsSolid && item.EstimatedSizeIsDefined)
- size = item.EstimatedSize;
+ if (item.Size_Defined)
+ size = item.Size;
+ else if (_archive.IsSolid && item.EstimatedSize_Defined)
+ size = item.EstimatedSize;
else
return false;
return true;
}
-bool CHandler::GetCompressedSize(int index, UInt32 &size)
+bool CHandler::GetCompressedSize(unsigned index, UInt32 &size) const
{
size = 0;
const CItem &item = _archive.Items[index];
- if (item.CompressedSizeIsDefined)
+ if (item.CompressedSize_Defined)
size = item.CompressedSize;
else
{
@@ -202,27 +274,42 @@ bool CHandler::GetCompressedSize(int index, UInt32 &size)
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
{
COM_TRY_BEGIN
- NWindows::NCOM::CPropVariant prop;
+ NCOM::CPropVariant prop;
#ifdef NSIS_SCRIPT
if (index >= (UInt32)_archive.Items.Size())
{
- switch(propID)
+ if (index == (UInt32)_archive.Items.Size())
{
- case kpidPath: prop = L"[NSIS].nsi"; break;
- case kpidSize:
- case kpidPackSize: prop = (UInt64)_archive.Script.Length(); break;
- case kpidSolid: prop = false; break;
+ switch (propID)
+ {
+ case kpidPath: prop = "[NSIS].nsi"; break;
+ case kpidSize:
+ case kpidPackSize: prop = (UInt64)_archive.Script.Len(); break;
+ case kpidSolid: prop = false; break;
+ }
+ }
+ else
+ {
+ const CLicenseFile &lic = _archive.LicenseFiles[index - (_archive.Items.Size() + 1)];
+ switch (propID)
+ {
+ case kpidPath: prop = lic.Name; break;
+ case kpidSize:
+ case kpidPackSize: prop = (UInt64)lic.Size; break;
+ case kpidSolid: prop = false; break;
+ }
}
}
else
#endif
{
const CItem &item = _archive.Items[index];
- switch(propID)
+ switch (propID)
{
+ case kpidOffset: prop = item.Pos; break;
case kpidPath:
{
- UString s = NItemName::WinNameToOSName(item.GetReducedName(_archive.IsUnicode));
+ UString s = NItemName::WinNameToOSName(_archive.GetReducedName(index));
if (!s.IsEmpty())
prop = (const wchar_t *)s;
break;
@@ -248,7 +335,21 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
prop = item.MTime;
break;
}
- case kpidMethod: prop = GetMethod(item.UseFilter, item.DictionarySize); break;
+ case kpidAttrib:
+ {
+ if (item.Attrib_Defined)
+ prop = item.Attrib;
+ break;
+ }
+
+ case kpidMethod:
+ if (_archive.IsSolid)
+ prop = _methodString;
+ else
+ prop = GetMethod(_archive.UseFilter, item.IsCompressed ? _archive.Method :
+ NMethodType::kCopy, item.DictionarySize);
+ break;
+
case kpidSolid: prop = _archive.IsSolid; break;
}
}
@@ -257,24 +358,56 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
COM_TRY_END
}
+
+static bool UninstallerPatch(const Byte *p, size_t size, CByteBuffer &dest)
+{
+ for (;;)
+ {
+ if (size < 4)
+ return false;
+ UInt32 len = Get32(p);
+ if (len == 0)
+ return size == 4;
+ if (size < 8)
+ return false;
+ UInt32 offs = Get32(p + 4);
+ p += 8;
+ size -= 8;
+ if (size < len || offs > dest.Size() || len > dest.Size() - offs)
+ return false;
+ memcpy(dest + offs, p, len);
+ p += len;
+ size -= len;
+ }
+}
+
+
STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
Int32 testMode, IArchiveExtractCallback *extractCallback)
{
COM_TRY_BEGIN
- bool allFilesMode = (numItems == (UInt32)-1);
+ bool allFilesMode = (numItems == (UInt32)(Int32)-1);
if (allFilesMode)
GetNumberOfItems(&numItems);
if (numItems == 0)
return S_OK;
+
UInt64 totalSize = 0;
+ UInt64 solidPosMax = 0;
UInt32 i;
for (i = 0; i < numItems; i++)
{
UInt32 index = (allFilesMode ? i : indices[i]);
+
#ifdef NSIS_SCRIPT
- if (index >= (UInt32)_archive.Items.Size())
- totalSize += _archive.Script.Length();
+ if (index >= _archive.Items.Size())
+ {
+ if (index == _archive.Items.Size())
+ totalSize += _archive.Script.Len();
+ else
+ totalSize += _archive.LicenseFiles[index - (_archive.Items.Size() + 1)].Size;
+ }
else
#endif
{
@@ -282,9 +415,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
if (_archive.IsSolid)
{
GetUncompressedSize(index, size);
- UInt64 pos = _archive.GetPosOfSolidItem(index);
- if (pos > totalSize)
- totalSize = pos + size;
+ UInt64 pos = (UInt64)_archive.GetPosOfSolidItem(index) + size;
+ if (solidPosMax < pos)
+ solidPosMax = pos;
}
else
{
@@ -293,33 +426,58 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
}
}
}
- extractCallback->SetTotal(totalSize);
- UInt64 currentTotalSize = 0;
- UInt32 currentItemSize = 0;
+ extractCallback->SetTotal(totalSize + solidPosMax);
+
+ CLocalProgress *lps = new CLocalProgress;
+ CMyComPtr<ICompressProgressInfo> progress = lps;
+ lps->Init(extractCallback, !_archive.IsSolid);
- UInt64 streamPos = 0;
if (_archive.IsSolid)
{
- RINOK(_inStream->Seek(_archive.StreamOffset, STREAM_SEEK_SET, NULL));
- bool useFilter;
- RINOK(_archive.Decoder.Init(
- EXTERNAL_CODECS_VARS
- _inStream, _archive.Method, _archive.FilterFlag, useFilter));
+ RINOK(_archive.SeekTo_DataStreamOffset());
+ RINOK(_archive.InitDecoder());
+ _archive.Decoder.StreamPos = 0;
}
- CByteBuffer byteBuf;
- const UInt32 kBufferLength = 1 << 16;
- byteBuf.SetCapacity(kBufferLength);
- Byte *buffer = byteBuf;
+ /* We use tempBuf for solid archives, if there is duplicate item.
+ We don't know uncompressed size for non-solid archives, so we can't
+ allocate exact buffer.
+ We use tempBuf also for first part (EXE stub) of unistall.exe
+ and tempBuf2 is used for second part (NSIS script). */
CByteBuffer tempBuf;
-
- bool dataError = false;
- for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize)
+ CByteBuffer tempBuf2;
+
+ /* tempPos is pos in uncompressed stream of previous item for solid archive, that
+ was written to tempBuf */
+ UInt64 tempPos = (UInt64)(Int64)-1;
+
+ /* prevPos is pos in uncompressed stream of previous item for solid archive.
+ It's used for test mode (where we don't need to test same file second time */
+ UInt64 prevPos = (UInt64)(Int64)-1;
+
+ // if there is error in solid archive, we show error for all subsequent files
+ bool solidDataError = false;
+
+ UInt64 curTotalPacked = 0, curTotalUnpacked = 0;
+ UInt32 curPacked = 0;
+ UInt64 curUnpacked = 0;
+
+ for (i = 0; i < numItems; i++,
+ curTotalPacked += curPacked,
+ curTotalUnpacked += curUnpacked)
{
- currentItemSize = 0;
- RINOK(extractCallback->SetCompleted(&currentTotalSize));
+ lps->InSize = curTotalPacked;
+ lps->OutSize = curTotalUnpacked;
+ if (_archive.IsSolid)
+ lps->OutSize += _archive.Decoder.StreamPos;
+
+ curPacked = 0;
+ curUnpacked = 0;
+ RINOK(lps->SetCur());
+
+ // RINOK(extractCallback->SetCompleted(&currentTotalSize));
CMyComPtr<ISequentialOutStream> realOutStream;
Int32 askMode = testMode ?
NExtract::NAskMode::kTest :
@@ -328,169 +486,184 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
+ bool dataError = false;
+
#ifdef NSIS_SCRIPT
if (index >= (UInt32)_archive.Items.Size())
{
- currentItemSize = _archive.Script.Length();
+ const void *data;
+ size_t size;
+ if (index == (UInt32)_archive.Items.Size())
+ {
+ data = (const Byte *)_archive.Script;
+ size = _archive.Script.Len();
+ }
+ else
+ {
+ CLicenseFile &lic = _archive.LicenseFiles[index - (_archive.Items.Size() + 1)];
+ if (lic.Text.Size() != 0)
+ data = lic.Text;
+ else
+ data = _archive._data + lic.Offset;
+ size = lic.Size;
+ }
+ curUnpacked = size;
if (!testMode && !realOutStream)
continue;
RINOK(extractCallback->PrepareOperation(askMode));
- if (!testMode)
- RINOK(WriteStream(realOutStream, (const char *)_archive.Script, (UInt32)_archive.Script.Length()));
+ if (realOutStream)
+ RINOK(WriteStream(realOutStream, data, size));
}
else
#endif
{
const CItem &item = _archive.Items[index];
- if (_archive.IsSolid)
- GetUncompressedSize(index, currentItemSize);
- else
- GetCompressedSize(index, currentItemSize);
+ if (!_archive.IsSolid)
+ GetCompressedSize(index, curPacked);
if (!testMode && !realOutStream)
continue;
RINOK(extractCallback->PrepareOperation(askMode));
- if (!dataError)
+ dataError = solidDataError;
+
+ bool needDecompress = !solidDataError;
+ if (needDecompress)
{
- bool needDecompress = false;
- bool sizeIsKnown = false;
- UInt32 fullSize = 0;
+ if (testMode && _archive.IsSolid && _archive.GetPosOfSolidItem(index) == prevPos)
+ needDecompress = false;
+ }
+ if (needDecompress)
+ {
bool writeToTemp = false;
bool readFromTemp = false;
- if (_archive.IsSolid)
+ if (!_archive.IsSolid)
+ {
+ RINOK(_archive.SeekToNonSolidItem(index));
+ }
+ else
{
UInt64 pos = _archive.GetPosOfSolidItem(index);
- while (streamPos < pos)
+ if (pos < _archive.Decoder.StreamPos)
+ {
+ if (pos != tempPos)
+ solidDataError = dataError = true;
+ readFromTemp = true;
+ }
+ else
{
- size_t processedSize = (UInt32)MyMin(pos - streamPos, (UInt64)kBufferLength);
- HRESULT res = _archive.Decoder.Read(buffer, &processedSize);
+ HRESULT res = _archive.Decoder.SetToPos(pos, progress);
if (res != S_OK)
{
if (res != S_FALSE)
return res;
- dataError = true;
- break;
+ solidDataError = dataError = true;
}
- if (processedSize == 0)
+ else if (!testMode && i + 1 < numItems)
{
- dataError = true;
- break;
+ UInt32 next = allFilesMode ? i + 1 : indices[i + 1];
+ if (next < _archive.Items.Size())
+ {
+ UInt64 nextPos = _archive.GetPosOfSolidItem(next);
+ if (nextPos == pos)
+ {
+ writeToTemp = true;
+ tempPos = pos;
+ }
+ }
}
- streamPos += processedSize;
}
- if (streamPos == pos)
+ prevPos = pos;
+ }
+
+ if (!dataError)
+ {
+ UInt32 unpackSize = 0;
+ bool unpackSize_Defined = false;
+ bool writeToTemp1 = writeToTemp;
+ if (item.IsUninstaller)
{
- Byte buffer2[4];
- size_t processedSize = 4;
- RINOK(_archive.Decoder.Read(buffer2, &processedSize));
- if (processedSize != 4)
- return E_FAIL;
- streamPos += processedSize;
- fullSize = Get32(buffer2);
- sizeIsKnown = true;
- needDecompress = true;
-
- if (!testMode && i + 1 < numItems)
+ unpackSize = item.PatchSize;
+ unpackSize_Defined = true;
+ if (!readFromTemp)
+ writeToTemp = true;
+ writeToTemp1 = writeToTemp;
+ if (_archive.ExeStub.Size() == 0)
{
- UInt64 nextPos = _archive.GetPosOfSolidItem(allFilesMode ? i : indices[i + 1]);
- if (nextPos < streamPos + fullSize)
- {
+ if (writeToTemp1 && !readFromTemp)
tempBuf.Free();
- tempBuf.SetCapacity(fullSize);
- writeToTemp = true;
- }
+ writeToTemp1 = false;
}
}
- else
- readFromTemp = true;
- }
- else
- {
- RINOK(_inStream->Seek(_archive.GetPosOfNonSolidItem(index) + 4, STREAM_SEEK_SET, NULL));
- if (item.IsCompressed)
+
+ if (readFromTemp)
{
- needDecompress = true;
- bool useFilter;
- RINOK(_archive.Decoder.Init(
- EXTERNAL_CODECS_VARS
- _inStream, _archive.Method, _archive.FilterFlag, useFilter));
- // fullSize = Get32(buffer); // It's bug !!!
- // Test it: what is exact fullSize?
- fullSize = 0xFFFFFFFF;
+ if (realOutStream && !item.IsUninstaller)
+ RINOK(WriteStream(realOutStream, tempBuf, tempBuf.Size()));
}
else
- fullSize = item.Size;
- }
- if (!dataError)
- {
- if (needDecompress)
{
- UInt64 offset = 0;
- while (!sizeIsKnown || fullSize > 0)
+ UInt32 curUnpacked32 = 0;
+ HRESULT res = _archive.Decoder.Decode(
+ writeToTemp1 ? &tempBuf : NULL,
+ item.IsUninstaller, item.PatchSize,
+ item.IsUninstaller ? NULL : realOutStream,
+ progress,
+ curPacked, curUnpacked32);
+ curUnpacked = curUnpacked32;
+ if (_archive.IsSolid)
+ curUnpacked = 0;
+ if (res != S_OK)
{
- UInt32 curSize = kBufferLength;
- if (sizeIsKnown && curSize > fullSize)
- curSize = fullSize;
- size_t processedSize = curSize;
- HRESULT res = _archive.Decoder.Read(buffer, &processedSize);
- if (res != S_OK)
- {
- if (res != S_FALSE)
- return res;
- dataError = true;
- break;
- }
- if (processedSize == 0)
- {
- if (sizeIsKnown)
- dataError = true;
- break;
- }
-
- if (writeToTemp)
- memcpy((Byte *)tempBuf + (size_t)offset, buffer, processedSize);
-
- fullSize -= (UInt32)processedSize;
- streamPos += processedSize;
- offset += processedSize;
-
- UInt64 completed;
+ if (res != S_FALSE)
+ return res;
+ dataError = true;
if (_archive.IsSolid)
- completed = currentTotalSize + offset;
- else
- completed = streamPos;
- RINOK(extractCallback->SetCompleted(&completed));
- if (!testMode)
- RINOK(WriteStream(realOutStream, buffer, processedSize));
+ solidDataError = true;
}
}
+ }
+
+ if (!dataError && item.IsUninstaller)
+ {
+ if (_archive.ExeStub.Size() != 0)
+ {
+ CByteBuffer destBuf = _archive.ExeStub;
+ dataError = !UninstallerPatch(tempBuf, tempBuf.Size(), destBuf);
+
+ if (realOutStream)
+ RINOK(WriteStream(realOutStream, destBuf, destBuf.Size()));
+ }
+
+ if (readFromTemp)
+ {
+ if (realOutStream)
+ RINOK(WriteStream(realOutStream, tempBuf2, tempBuf2.Size()));
+ }
else
{
- if (readFromTemp)
- {
- if (!testMode)
- RINOK(WriteStream(realOutStream, tempBuf, tempBuf.GetCapacity()));
- }
- else
- while (fullSize > 0)
+ UInt32 curPacked2 = 0;
+ UInt32 curUnpacked2 = 0;
+ HRESULT res = _archive.Decoder.Decode(
+ writeToTemp ? &tempBuf2 : NULL,
+ false, 0,
+ realOutStream,
+ progress,
+ curPacked2, curUnpacked2);
+ curPacked += curPacked2;
+ if (!_archive.IsSolid)
+ curUnpacked += curUnpacked2;
+ if (res != S_OK)
{
- UInt32 curSize = MyMin(fullSize, kBufferLength);
- UInt32 processedSize;
- RINOK(_inStream->Read(buffer, curSize, &processedSize));
- if (processedSize == 0)
- {
- dataError = true;
- break;
- }
- fullSize -= processedSize;
- streamPos += processedSize;
- if (!testMode)
- RINOK(WriteStream(realOutStream, buffer, processedSize));
+ if (res != S_FALSE)
+ return res;
+ dataError = true;
+ if (_archive.IsSolid)
+ solidDataError = true;
}
}
}
@@ -505,6 +678,4 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
COM_TRY_END
}
-IMPL_ISetCompressCodecsInfo
-
}}