aboutsummaryrefslogtreecommitdiff
path: root/CPP/7zip/Archive/Nsis/NsisHandler.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--CPP/7zip/Archive/Nsis/NsisHandler.cpp126
1 files changed, 66 insertions, 60 deletions
diff --git a/CPP/7zip/Archive/Nsis/NsisHandler.cpp b/CPP/7zip/Archive/Nsis/NsisHandler.cpp
index aa0a917..7a512b7 100644
--- a/CPP/7zip/Archive/Nsis/NsisHandler.cpp
+++ b/CPP/7zip/Archive/Nsis/NsisHandler.cpp
@@ -61,22 +61,19 @@ IMP_IInArchive_Props
61IMP_IInArchive_ArcProps 61IMP_IInArchive_ArcProps
62 62
63 63
64static AString UInt32ToString(UInt32 val) 64static void AddDictProp(AString &s, UInt32 val)
65{ 65{
66 char s[16]; 66 for (unsigned i = 0; i < 32; i++)
67 ConvertUInt32ToString(val, s);
68 return (AString)s;
69}
70
71static AString GetStringForSizeValue(UInt32 val)
72{
73 for (int i = 31; i >= 0; i--)
74 if (((UInt32)1 << i) == val) 67 if (((UInt32)1 << i) == val)
75 return UInt32ToString(i); 68 {
69 s.Add_UInt32(i);
70 return;
71 }
76 char c = 'b'; 72 char c = 'b';
77 if ((val & ((1 << 20) - 1)) == 0) { val >>= 20; c = 'm'; } 73 if ((val & ((1 << 20) - 1)) == 0) { val >>= 20; c = 'm'; }
78 else if ((val & ((1 << 10) - 1)) == 0) { val >>= 10; c = 'k'; } 74 else if ((val & ((1 << 10) - 1)) == 0) { val >>= 10; c = 'k'; }
79 return UInt32ToString(val) + c; 75 s.Add_UInt32(val);
76 s += c;
80} 77}
81 78
82static AString GetMethod(bool useFilter, NMethodType::EEnum method, UInt32 dict) 79static AString GetMethod(bool useFilter, NMethodType::EEnum method, UInt32 dict)
@@ -87,11 +84,11 @@ static AString GetMethod(bool useFilter, NMethodType::EEnum method, UInt32 dict)
87 s += kBcjMethod; 84 s += kBcjMethod;
88 s.Add_Space(); 85 s.Add_Space();
89 } 86 }
90 s += ((unsigned)method < ARRAY_SIZE(kMethods)) ? kMethods[(unsigned)method] : kUnknownMethod; 87 s += ((unsigned)method < Z7_ARRAY_SIZE(kMethods)) ? kMethods[(unsigned)method] : kUnknownMethod;
91 if (method == NMethodType::kLZMA) 88 if (method == NMethodType::kLZMA)
92 { 89 {
93 s += ':'; 90 s += ':';
94 s += GetStringForSizeValue(dict); 91 AddDictProp(s, dict);
95 } 92 }
96 return s; 93 return s;
97} 94}
@@ -105,7 +102,7 @@ AString CHandler::GetMethod(NMethodType::EEnum method, bool useItemFilter, UInt3
105 s += kBcjMethod; 102 s += kBcjMethod;
106 s.Add_Space(); 103 s.Add_Space();
107 } 104 }
108 s += (method < ARRAY_SIZE(kMethods)) ? kMethods[method] : kUnknownMethod; 105 s += (method < Z7_ARRAY_SIZE(kMethods)) ? kMethods[method] : kUnknownMethod;
109 if (method == NMethodType::kLZMA) 106 if (method == NMethodType::kLZMA)
110 { 107 {
111 s += ':'; 108 s += ':';
@@ -115,7 +112,7 @@ AString CHandler::GetMethod(NMethodType::EEnum method, bool useItemFilter, UInt3
115} 112}
116*/ 113*/
117 114
118STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) 115Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
119{ 116{
120 COM_TRY_BEGIN 117 COM_TRY_BEGIN
121 NCOM::CPropVariant prop; 118 NCOM::CPropVariant prop;
@@ -162,7 +159,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
162 if (!_archive.IsInstaller) 159 if (!_archive.IsInstaller)
163 { 160 {
164 if (!s.IsEmpty()) 161 if (!s.IsEmpty())
165 s += '.'; 162 s.Add_Dot();
166 s += "Uninstall"; 163 s += "Uninstall";
167 } 164 }
168 #endif 165 #endif
@@ -190,7 +187,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
190} 187}
191 188
192 189
193STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback * /* openArchiveCallback */) 190Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback * /* openArchiveCallback */))
194{ 191{
195 COM_TRY_BEGIN 192 COM_TRY_BEGIN
196 Close(); 193 Close();
@@ -215,18 +212,18 @@ STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *maxCheckStartPositi
215 COM_TRY_END 212 COM_TRY_END
216} 213}
217 214
218STDMETHODIMP CHandler::Close() 215Z7_COM7F_IMF(CHandler::Close())
219{ 216{
220 _archive.Clear(); 217 _archive.Clear();
221 _archive.Release(); 218 _archive.Release();
222 return S_OK; 219 return S_OK;
223} 220}
224 221
225STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) 222Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
226{ 223{
227 *numItems = _archive.Items.Size() 224 *numItems = _archive.Items.Size()
228 #ifdef NSIS_SCRIPT 225 #ifdef NSIS_SCRIPT
229 + 1 + _archive.LicenseFiles.Size(); 226 + 1 + _archive.LicenseFiles.Size()
230 #endif 227 #endif
231 ; 228 ;
232 return S_OK; 229 return S_OK;
@@ -240,7 +237,7 @@ bool CHandler::GetUncompressedSize(unsigned index, UInt32 &size) const
240 size = item.Size; 237 size = item.Size;
241 else if (_archive.IsSolid && item.EstimatedSize_Defined) 238 else if (_archive.IsSolid && item.EstimatedSize_Defined)
242 size = item.EstimatedSize; 239 size = item.EstimatedSize;
243 else 240 else if (!item.IsEmptyFile)
244 return false; 241 return false;
245 return true; 242 return true;
246} 243}
@@ -272,7 +269,7 @@ bool CHandler::GetCompressedSize(unsigned index, UInt32 &size) const
272} 269}
273 270
274 271
275STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) 272Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))
276{ 273{
277 COM_TRY_BEGIN 274 COM_TRY_BEGIN
278 NCOM::CPropVariant prop; 275 NCOM::CPropVariant prop;
@@ -360,21 +357,21 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
360} 357}
361 358
362 359
363static bool UninstallerPatch(const Byte *p, size_t size, CByteBuffer &dest) 360static bool UninstallerPatch(const Byte *p, size_t size, Byte *dest, size_t destSize)
364{ 361{
365 for (;;) 362 for (;;)
366 { 363 {
367 if (size < 4) 364 if (size < 4)
368 return false; 365 return false;
369 UInt32 len = Get32(p); 366 const UInt32 len = Get32(p);
370 if (len == 0) 367 if (len == 0)
371 return size == 4; 368 return size == 4;
372 if (size < 8) 369 if (size < 8)
373 return false; 370 return false;
374 UInt32 offs = Get32(p + 4); 371 const UInt32 offs = Get32(p + 4);
375 p += 8; 372 p += 8;
376 size -= 8; 373 size -= 8;
377 if (size < len || offs > dest.Size() || len > dest.Size() - offs) 374 if (size < len || offs > destSize || len > destSize - offs)
378 return false; 375 return false;
379 memcpy(dest + offs, p, len); 376 memcpy(dest + offs, p, len);
380 p += len; 377 p += len;
@@ -383,11 +380,11 @@ static bool UninstallerPatch(const Byte *p, size_t size, CByteBuffer &dest)
383} 380}
384 381
385 382
386STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, 383Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
387 Int32 testMode, IArchiveExtractCallback *extractCallback) 384 Int32 testMode, IArchiveExtractCallback *extractCallback))
388{ 385{
389 COM_TRY_BEGIN 386 COM_TRY_BEGIN
390 bool allFilesMode = (numItems == (UInt32)(Int32)-1); 387 const bool allFilesMode = (numItems == (UInt32)(Int32)-1);
391 if (allFilesMode) 388 if (allFilesMode)
392 GetNumberOfItems(&numItems); 389 GetNumberOfItems(&numItems);
393 if (numItems == 0) 390 if (numItems == 0)
@@ -399,7 +396,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
399 UInt32 i; 396 UInt32 i;
400 for (i = 0; i < numItems; i++) 397 for (i = 0; i < numItems; i++)
401 { 398 {
402 UInt32 index = (allFilesMode ? i : indices[i]); 399 const UInt32 index = (allFilesMode ? i : indices[i]);
403 400
404 #ifdef NSIS_SCRIPT 401 #ifdef NSIS_SCRIPT
405 if (index >= _archive.Items.Size()) 402 if (index >= _archive.Items.Size())
@@ -436,8 +433,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
436 433
437 if (_archive.IsSolid) 434 if (_archive.IsSolid)
438 { 435 {
439 RINOK(_archive.SeekTo_DataStreamOffset()); 436 RINOK(_archive.SeekTo_DataStreamOffset())
440 RINOK(_archive.InitDecoder()); 437 RINOK(_archive.InitDecoder())
441 _archive.Decoder.StreamPos = 0; 438 _archive.Decoder.StreamPos = 0;
442 } 439 }
443 440
@@ -476,16 +473,16 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
476 473
477 curPacked = 0; 474 curPacked = 0;
478 curUnpacked = 0; 475 curUnpacked = 0;
479 RINOK(lps->SetCur()); 476 RINOK(lps->SetCur())
480 477
481 // RINOK(extractCallback->SetCompleted(&currentTotalSize)); 478 // RINOK(extractCallback->SetCompleted(&currentTotalSize))
482 CMyComPtr<ISequentialOutStream> realOutStream; 479 CMyComPtr<ISequentialOutStream> realOutStream;
483 Int32 askMode = testMode ? 480 const Int32 askMode = testMode ?
484 NExtract::NAskMode::kTest : 481 NExtract::NAskMode::kTest :
485 NExtract::NAskMode::kExtract; 482 NExtract::NAskMode::kExtract;
486 const UInt32 index = allFilesMode ? i : indices[i]; 483 const UInt32 index = allFilesMode ? i : indices[i];
487 484
488 RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); 485 RINOK(extractCallback->GetStream(index, &realOutStream, askMode))
489 486
490 bool dataError = false; 487 bool dataError = false;
491 488
@@ -511,9 +508,9 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
511 curUnpacked = size; 508 curUnpacked = size;
512 if (!testMode && !realOutStream) 509 if (!testMode && !realOutStream)
513 continue; 510 continue;
514 RINOK(extractCallback->PrepareOperation(askMode)); 511 RINOK(extractCallback->PrepareOperation(askMode))
515 if (realOutStream) 512 if (realOutStream)
516 RINOK(WriteStream(realOutStream, data, size)); 513 RINOK(WriteStream(realOutStream, data, size))
517 } 514 }
518 else 515 else
519 #endif 516 #endif
@@ -526,15 +523,20 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
526 if (!testMode && !realOutStream) 523 if (!testMode && !realOutStream)
527 continue; 524 continue;
528 525
529 RINOK(extractCallback->PrepareOperation(askMode)); 526 RINOK(extractCallback->PrepareOperation(askMode))
530 527
531 dataError = solidDataError; 528 dataError = solidDataError;
532 529
533 bool needDecompress = !solidDataError; 530 bool needDecompress = false;
534 if (needDecompress) 531
532 if (!item.IsEmptyFile)
535 { 533 {
536 if (testMode && _archive.IsSolid && _archive.GetPosOfSolidItem(index) == prevPos) 534 needDecompress = !solidDataError;
537 needDecompress = false; 535 if (needDecompress)
536 {
537 if (testMode && _archive.IsSolid && _archive.GetPosOfSolidItem(index) == prevPos)
538 needDecompress = false;
539 }
538 } 540 }
539 541
540 if (needDecompress) 542 if (needDecompress)
@@ -544,7 +546,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
544 546
545 if (!_archive.IsSolid) 547 if (!_archive.IsSolid)
546 { 548 {
547 RINOK(_archive.SeekToNonSolidItem(index)); 549 RINOK(_archive.SeekToNonSolidItem(index))
548 } 550 }
549 else 551 else
550 { 552 {
@@ -566,10 +568,11 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
566 } 568 }
567 else if (!testMode && i + 1 < numItems) 569 else if (!testMode && i + 1 < numItems)
568 { 570 {
569 UInt32 next = allFilesMode ? i + 1 : indices[i + 1]; 571 const UInt32 next = allFilesMode ? i + 1 : indices[i + 1];
570 if (next < _archive.Items.Size()) 572 if (next < _archive.Items.Size())
571 { 573 {
572 UInt64 nextPos = _archive.GetPosOfSolidItem(next); 574 // next cannot be IsEmptyFile
575 const UInt64 nextPos = _archive.GetPosOfSolidItem(next);
573 if (nextPos == pos) 576 if (nextPos == pos)
574 { 577 {
575 writeToTemp = true; 578 writeToTemp = true;
@@ -581,12 +584,16 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
581 prevPos = pos; 584 prevPos = pos;
582 } 585 }
583 586
587 /* nsis 3.08 can use (PatchSize == 0) for uninstaller without patched section */
588
589 const bool is_PatchedUninstaller = item.Is_PatchedUninstaller();
590
584 if (!dataError) 591 if (!dataError)
585 { 592 {
586 // UInt32 unpackSize = 0; 593 // UInt32 unpackSize = 0;
587 // bool unpackSize_Defined = false; 594 // bool unpackSize_Defined = false;
588 bool writeToTemp1 = writeToTemp; 595 bool writeToTemp1 = writeToTemp;
589 if (item.IsUninstaller) 596 if (is_PatchedUninstaller)
590 { 597 {
591 // unpackSize = item.PatchSize; 598 // unpackSize = item.PatchSize;
592 // unpackSize_Defined = true; 599 // unpackSize_Defined = true;
@@ -603,16 +610,16 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
603 610
604 if (readFromTemp) 611 if (readFromTemp)
605 { 612 {
606 if (realOutStream && !item.IsUninstaller) 613 if (realOutStream && !is_PatchedUninstaller)
607 RINOK(WriteStream(realOutStream, tempBuf, tempBuf.Size())); 614 RINOK(WriteStream(realOutStream, tempBuf, tempBuf.Size()))
608 } 615 }
609 else 616 else
610 { 617 {
611 UInt32 curUnpacked32 = 0; 618 UInt32 curUnpacked32 = 0;
612 HRESULT res = _archive.Decoder.Decode( 619 const HRESULT res = _archive.Decoder.Decode(
613 writeToTemp1 ? &tempBuf : NULL, 620 writeToTemp1 ? &tempBuf : NULL,
614 item.IsUninstaller, item.PatchSize, 621 is_PatchedUninstaller, item.PatchSize,
615 item.IsUninstaller ? NULL : (ISequentialOutStream *)realOutStream, 622 is_PatchedUninstaller ? NULL : (ISequentialOutStream *)realOutStream,
616 progress, 623 progress,
617 curPacked, curUnpacked32); 624 curPacked, curUnpacked32);
618 curUnpacked = curUnpacked32; 625 curUnpacked = curUnpacked32;
@@ -629,21 +636,20 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
629 } 636 }
630 } 637 }
631 638
632 if (!dataError && item.IsUninstaller) 639 if (!dataError && is_PatchedUninstaller)
633 { 640 {
634 if (_archive.ExeStub.Size() != 0) 641 if (_archive.ExeStub.Size() != 0)
635 { 642 {
636 CByteBuffer destBuf = _archive.ExeStub; 643 CByteBuffer destBuf = _archive.ExeStub;
637 dataError = !UninstallerPatch(tempBuf, tempBuf.Size(), destBuf); 644 dataError = !UninstallerPatch(tempBuf, tempBuf.Size(), destBuf, destBuf.Size());
638
639 if (realOutStream) 645 if (realOutStream)
640 RINOK(WriteStream(realOutStream, destBuf, destBuf.Size())); 646 RINOK(WriteStream(realOutStream, destBuf, destBuf.Size()))
641 } 647 }
642 648
643 if (readFromTemp) 649 if (readFromTemp)
644 { 650 {
645 if (realOutStream) 651 if (realOutStream)
646 RINOK(WriteStream(realOutStream, tempBuf2, tempBuf2.Size())); 652 RINOK(WriteStream(realOutStream, tempBuf2, tempBuf2.Size()))
647 } 653 }
648 else 654 else
649 { 655 {
@@ -652,10 +658,10 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
652 658
653 if (!_archive.IsSolid) 659 if (!_archive.IsSolid)
654 { 660 {
655 RINOK(_archive.SeekTo(_archive.GetPosOfNonSolidItem(index) + 4 + curPacked )); 661 RINOK(_archive.SeekTo(_archive.GetPosOfNonSolidItem(index) + 4 + curPacked ))
656 } 662 }
657 663
658 HRESULT res = _archive.Decoder.Decode( 664 const HRESULT res = _archive.Decoder.Decode(
659 writeToTemp ? &tempBuf2 : NULL, 665 writeToTemp ? &tempBuf2 : NULL,
660 false, 0, 666 false, 0,
661 realOutStream, 667 realOutStream,
@@ -679,7 +685,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
679 realOutStream.Release(); 685 realOutStream.Release();
680 RINOK(extractCallback->SetOperationResult(dataError ? 686 RINOK(extractCallback->SetOperationResult(dataError ?
681 NExtract::NOperationResult::kDataError : 687 NExtract::NOperationResult::kDataError :
682 NExtract::NOperationResult::kOK)); 688 NExtract::NOperationResult::kOK))
683 } 689 }
684 return S_OK; 690 return S_OK;
685 COM_TRY_END 691 COM_TRY_END