diff options
Diffstat (limited to 'src/libs/7zip/unix/CPP/7zip/Archive/PeHandler.cpp')
-rw-r--r-- | src/libs/7zip/unix/CPP/7zip/Archive/PeHandler.cpp | 1752 |
1 files changed, 0 insertions, 1752 deletions
diff --git a/src/libs/7zip/unix/CPP/7zip/Archive/PeHandler.cpp b/src/libs/7zip/unix/CPP/7zip/Archive/PeHandler.cpp deleted file mode 100644 index c64067aa5..000000000 --- a/src/libs/7zip/unix/CPP/7zip/Archive/PeHandler.cpp +++ /dev/null @@ -1,1752 +0,0 @@ -// PeHandler.cpp - -#include "StdAfx.h" - -#include "../../../C/CpuArch.h" - -#include "Common/DynamicBuffer.h" -#include "Common/ComTry.h" -#include "Common/IntToString.h" -#include "Common/StringConvert.h" - -#include "Windows/PropVariantUtils.h" -#include "Windows/Time.h" - -#include "../Common/LimitedStreams.h" -#include "../Common/ProgressUtils.h" -#include "../Common/RegisterArc.h" -#include "../Common/StreamObjects.h" -#include "../Common/StreamUtils.h" - -#include "../Compress/CopyCoder.h" - -#define Get16(p) GetUi16(p) -#define Get32(p) GetUi32(p) -#define Get64(p) GetUi64(p) - -using namespace NWindows; - -namespace NArchive { -namespace NPe { - -#define NUM_SCAN_SECTIONS_MAX (1 << 6) - -#define PE_SIG 0x00004550 -#define PE_OptHeader_Magic_32 0x10B -#define PE_OptHeader_Magic_64 0x20B - -static AString GetDecString(UInt32 v) -{ - char sz[32]; - ConvertUInt64ToString(v, sz); - return sz; -} - -struct CVersion -{ - UInt16 Major; - UInt16 Minor; - - void Parse(const Byte *buf); - AString GetString() const { return GetDecString(Major) + '.' + GetDecString(Minor); } -}; - -void CVersion::Parse(const Byte *p) -{ - Major = Get16(p); - Minor = Get16(p + 2); -} - -static const UInt32 kHeaderSize = 4 + 20; - -struct CHeader -{ - UInt16 NumSections; - UInt32 Time; - UInt32 PointerToSymbolTable; - UInt32 NumSymbols; - UInt16 OptHeaderSize; - UInt16 Flags; - UInt16 Machine; - - bool Parse(const Byte *buf); -}; - -bool CHeader::Parse(const Byte *p) -{ - if (Get32(p) != PE_SIG) - return false; - p += 4; - Machine = Get16(p + 0); - NumSections = Get16(p + 2); - Time = Get32(p + 4); - PointerToSymbolTable = Get32(p + 8); - NumSymbols = Get32(p + 12); - OptHeaderSize = Get16(p + 16); - Flags = Get16(p + 18); - return true; -} - -struct CDirLink -{ - UInt32 Va; - UInt32 Size; - void Parse(const Byte *p); -}; - -void CDirLink::Parse(const Byte *p) -{ - Va = Get32(p); - Size = Get32(p + 4); -} - -enum -{ - kDirLink_Certificate = 4, - kDirLink_Debug = 6 -}; - -struct CDebugEntry -{ - UInt32 Flags; - UInt32 Time; - CVersion Ver; - UInt32 Type; - UInt32 Size; - UInt32 Va; - UInt32 Pa; - - void Parse(const Byte *p); -}; - -void CDebugEntry::Parse(const Byte *p) -{ - Flags = Get32(p); - Time = Get32(p + 4); - Ver.Parse(p + 8); - Type = Get32(p + 12); - Size = Get32(p + 16); - Va = Get32(p + 20); - Pa = Get32(p + 24); -} - -static const UInt32 kNumDirItemsMax = 16; - -struct COptHeader -{ - UInt16 Magic; - Byte LinkerVerMajor; - Byte LinkerVerMinor; - - UInt32 CodeSize; - UInt32 InitDataSize; - UInt32 UninitDataSize; - - // UInt32 AddressOfEntryPoint; - // UInt32 BaseOfCode; - // UInt32 BaseOfData32; - UInt64 ImageBase; - - UInt32 SectAlign; - UInt32 FileAlign; - - CVersion OsVer; - CVersion ImageVer; - CVersion SubsysVer; - - UInt32 ImageSize; - UInt32 HeadersSize; - UInt32 CheckSum; - UInt16 SubSystem; - UInt16 DllCharacts; - - UInt64 StackReserve; - UInt64 StackCommit; - UInt64 HeapReserve; - UInt64 HeapCommit; - - UInt32 NumDirItems; - CDirLink DirItems[kNumDirItemsMax]; - - bool Is64Bit() const { return Magic == PE_OptHeader_Magic_64; } - bool Parse(const Byte *p, UInt32 size); - - int GetNumFileAlignBits() const - { - for (int i = 9; i <= 16; i++) - if (((UInt32)1 << i) == FileAlign) - return i; - return -1; - } -}; - -bool COptHeader::Parse(const Byte *p, UInt32 size) -{ - Magic = Get16(p); - switch (Magic) - { - case PE_OptHeader_Magic_32: - case PE_OptHeader_Magic_64: - break; - default: - return false; - } - LinkerVerMajor = p[2]; - LinkerVerMinor = p[3]; - - bool hdr64 = Is64Bit(); - - CodeSize = Get32(p + 4); - InitDataSize = Get32(p + 8); - UninitDataSize = Get32(p + 12); - - // AddressOfEntryPoint = Get32(p + 16); - // BaseOfCode = Get32(p + 20); - // BaseOfData32 = hdr64 ? 0: Get32(p + 24); - ImageBase = hdr64 ? GetUi64(p + 24) : Get32(p + 28); - - SectAlign = Get32(p + 32); - FileAlign = Get32(p + 36); - - OsVer.Parse(p + 40); - ImageVer.Parse(p + 44); - SubsysVer.Parse(p + 48); - - // reserved = Get32(p + 52); - - ImageSize = Get32(p + 56); - HeadersSize = Get32(p + 60); - CheckSum = Get32(p + 64); - SubSystem = Get16(p + 68); - DllCharacts = Get16(p + 70); - - if (hdr64) - { - StackReserve = Get64(p + 72); - StackCommit = Get64(p + 80); - HeapReserve = Get64(p + 88); - HeapCommit = Get64(p + 96); - } - else - { - StackReserve = Get32(p + 72); - StackCommit = Get32(p + 76); - HeapReserve = Get32(p + 80); - HeapCommit = Get32(p + 84); - } - UInt32 pos = (hdr64 ? 108 : 92); - NumDirItems = Get32(p + pos); - pos += 4; - if (pos + 8 * NumDirItems != size) - return false; - for (UInt32 i = 0; i < NumDirItems && i < kNumDirItemsMax; i++) - DirItems[i].Parse(p + pos + i * 8); - return true; -} - -static const UInt32 kSectionSize = 40; - -struct CSection -{ - AString Name; - - UInt32 VSize; - UInt32 Va; - UInt32 PSize; - UInt32 Pa; - UInt32 Flags; - UInt32 Time; - // UInt16 NumRelocs; - bool IsDebug; - bool IsRealSect; - bool IsAdditionalSection; - - CSection(): IsRealSect(false), IsDebug(false), IsAdditionalSection(false) {} - UInt64 GetPackSize() const { return PSize; } - - void UpdateTotalSize(UInt32 &totalSize) - { - UInt32 t = Pa + PSize; - if (t > totalSize) - totalSize = t; - } - void Parse(const Byte *p); -}; - -static bool operator <(const CSection &a1, const CSection &a2) { return (a1.Pa < a2.Pa) || ((a1.Pa == a2.Pa) && (a1.PSize < a2.PSize)) ; } -static bool operator ==(const CSection &a1, const CSection &a2) { return (a1.Pa == a2.Pa) && (a1.PSize == a2.PSize); } - -static AString GetName(const Byte *name) -{ - const int kNameSize = 8; - AString res; - char *p = res.GetBuffer(kNameSize); - memcpy(p, name, kNameSize); - p[kNameSize] = 0; - res.ReleaseBuffer(); - return res; -} - -void CSection::Parse(const Byte *p) -{ - Name = GetName(p); - VSize = Get32(p + 8); - Va = Get32(p + 12); - PSize = Get32(p + 16); - Pa = Get32(p + 20); - // NumRelocs = Get16(p + 32); - Flags = Get32(p + 36); -} - -static const CUInt32PCharPair g_HeaderCharacts[] = -{ - { 1, "Executable" }, - { 13, "DLL" }, - { 8, "32-bit" }, - { 5, "LargeAddress" }, - { 0, "NoRelocs" }, - { 2, "NoLineNums" }, - { 3, "NoLocalSyms" }, - { 4, "AggressiveWsTrim" }, - { 9, "NoDebugInfo" }, - { 10, "RemovableRun" }, - { 11, "NetRun" }, - { 12, "System" }, - { 14, "UniCPU" }, - { 7, "Little-Endian" }, - { 15, "Big-Endian" } -}; - -static const CUInt32PCharPair g_DllCharacts[] = -{ - { 6, "Relocated" }, - { 7, "Integrity" }, - { 8, "NX-Compatible" }, - { 9, "NoIsolation" }, - { 10, "NoSEH" }, - { 11, "NoBind" }, - { 13, "WDM" }, - { 15, "TerminalServerAware" } -}; - -static const CUInt32PCharPair g_SectFlags[] = -{ - { 3, "NoPad" }, - { 5, "Code" }, - { 6, "InitializedData" }, - { 7, "UninitializedData" }, - { 9, "Comments" }, - { 11, "Remove" }, - { 12, "COMDAT" }, - { 15, "GP" }, - { 24, "ExtendedRelocations" }, - { 25, "Discardable" }, - { 26, "NotCached" }, - { 27, "NotPaged" }, - { 28, "Shared" }, - { 29, "Execute" }, - { 30, "Read" }, - { 31, "Write" } -}; - -static const CUInt32PCharPair g_MachinePairs[] = -{ - { 0x014C, "x86" }, - { 0x0162, "MIPS-R3000" }, - { 0x0166, "MIPS-R4000" }, - { 0x0168, "MIPS-R10000" }, - { 0x0169, "MIPS-V2" }, - { 0x0184, "Alpha" }, - { 0x01A2, "SH3" }, - { 0x01A3, "SH3-DSP" }, - { 0x01A4, "SH3E" }, - { 0x01A6, "SH4" }, - { 0x01A8, "SH5" }, - { 0x01C0, "ARM" }, - { 0x01C2, "ARM-Thumb" }, - { 0x01F0, "PPC" }, - { 0x01F1, "PPC-FP" }, - { 0x0200, "IA-64" }, - { 0x0284, "Alpha-64" }, - { 0x0200, "IA-64" }, - { 0x0366, "MIPSFPU" }, - { 0x8664, "x64" }, - { 0x0EBC, "EFI" } -}; - -static const CUInt32PCharPair g_SubSystems[] = -{ - { 0, "Unknown" }, - { 1, "Native" }, - { 2, "Windows GUI" }, - { 3, "Windows CUI" }, - { 7, "Posix" }, - { 9, "Windows CE" }, - { 10, "EFI" }, - { 11, "EFI Boot" }, - { 12, "EFI Runtime" }, - { 13, "EFI ROM" }, - { 14, "XBOX" } -}; - -static const wchar_t *g_ResTypes[] = -{ - NULL, - L"CURSOR", - L"BITMAP", - L"ICON", - L"MENU", - L"DIALOG", - L"STRING", - L"FONTDIR", - L"FONT", - L"ACCELERATOR", - L"RCDATA", - L"MESSAGETABLE", - L"GROUP_CURSOR", - NULL, - L"GROUP_ICON", - NULL, - L"VERSION", - L"DLGINCLUDE", - NULL, - L"PLUGPLAY", - L"VXD", - L"ANICURSOR", - L"ANIICON", - L"HTML", - L"MANIFEST" -}; - -const UInt32 kFlag = (UInt32)1 << 31; -const UInt32 kMask = ~kFlag; - -struct CTableItem -{ - UInt32 Offset; - UInt32 ID; -}; - - -const UInt32 kBmpHeaderSize = 14; -const UInt32 kIconHeaderSize = 22; - -struct CResItem -{ - UInt32 Type; - UInt32 ID; - UInt32 Lang; - - UInt32 Size; - UInt32 Offset; - - UInt32 HeaderSize; - Byte Header[kIconHeaderSize]; // it must be enough for max size header. - bool Enabled; - - bool IsNameEqual(const CResItem &item) const { return Lang == item.Lang; } - UInt32 GetSize() const { return Size + HeaderSize; } - bool IsBmp() const { return Type == 2; } - bool IsIcon() const { return Type == 3; } - bool IsString() const { return Type == 6; } - bool IsRcData() const { return Type == 10; } - bool IsRcDataOrUnknown() const { return IsRcData() || Type > 64; } -}; - -struct CStringItem -{ - UInt32 Lang; - UInt32 Size; - CByteDynamicBuffer Buf; - - void AddChar(Byte c); - void AddWChar(UInt16 c); -}; - -void CStringItem::AddChar(Byte c) -{ - Buf.EnsureCapacity(Size + 2); - Buf[Size++] = c; - Buf[Size++] = 0; -} - -void CStringItem::AddWChar(UInt16 c) -{ - if (c == '\n') - { - AddChar('\\'); - c = 'n'; - } - Buf.EnsureCapacity(Size + 2); - SetUi16(Buf + Size, c); - Size += 2; -} - -struct CMixItem -{ - int SectionIndex; - int ResourceIndex; - int StringIndex; - - bool IsSectionItem() const { return ResourceIndex < 0 && StringIndex < 0; }; -}; - -struct CUsedBitmap -{ - CByteBuffer Buf; -public: - void Alloc(size_t size) - { - size = (size + 7) / 8; - Buf.SetCapacity(size); - memset(Buf, 0, size); - } - void Free() - { - Buf.SetCapacity(0); - } - bool SetRange(size_t from, int size) - { - for (int i = 0; i < size; i++) - { - size_t pos = (from + i) >> 3; - Byte mask = (Byte)(1 << ((from + i) & 7)); - Byte b = Buf[pos]; - if ((b & mask) != 0) - return false; - Buf[pos] = b | mask; - } - return true; - } -}; - - -class CHandler: - public IInArchive, - public IInArchiveGetStream, - public CMyUnknownImp -{ - CMyComPtr<IInStream> _stream; - CObjectVector<CSection> _sections; - UInt32 _peOffset; - CHeader _header; - COptHeader _optHeader; - UInt32 _totalSize; - UInt32 _totalSizeLimited; - Int32 _mainSubfile; - - CRecordVector<CResItem> _items; - CObjectVector<CStringItem> _strings; - - CByteBuffer _buf; - bool _oneLang; - UString _resourceFileName; - CUsedBitmap _usedRes; - bool _parseResources; - - CRecordVector<CMixItem> _mixItems; - - HRESULT LoadDebugSections(IInStream *stream, bool &thereIsSection); - HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback); - bool Parse(const Byte *buf, UInt32 size); - - void AddResNameToString(UString &s, UInt32 id) const; - UString GetLangPrefix(UInt32 lang); - HRESULT ReadString(UInt32 offset, UString &dest) const; - HRESULT ReadTable(UInt32 offset, CRecordVector<CTableItem> &items); - bool ParseStringRes(UInt32 id, UInt32 lang, const Byte *src, UInt32 size); - HRESULT OpenResources(int sectIndex, IInStream *stream, IArchiveOpenCallback *callback); - void CloseResources(); - - - bool CheckItem(const CSection §, const CResItem &item, size_t offset) const - { - return item.Offset >= sect.Va && offset <= _buf.GetCapacity() && _buf.GetCapacity() - offset >= item.Size; - } - -public: - MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream) - INTERFACE_IInArchive(;) - STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream); -}; - -bool CHandler::Parse(const Byte *buf, UInt32 size) -{ - UInt32 i; - if (size < 512) - return false; - _peOffset = Get32(buf + 0x3C); - if (_peOffset >= 0x1000 || _peOffset + 512 > size || (_peOffset & 7) != 0) - return false; - - UInt32 pos = _peOffset; - if (!_header.Parse(buf + pos)) - return false; - if (_header.OptHeaderSize > 512 || _header.NumSections > NUM_SCAN_SECTIONS_MAX) - return false; - pos += kHeaderSize; - - if (!_optHeader.Parse(buf + pos, _header.OptHeaderSize)) - return false; - - pos += _header.OptHeaderSize; - _totalSize = pos; - - for (i = 0; i < _header.NumSections; i++, pos += kSectionSize) - { - CSection sect; - if (pos + kSectionSize > size) - return false; - sect.Parse(buf + pos); - sect.IsRealSect = true; - sect.UpdateTotalSize(_totalSize); - _sections.Add(sect); - } - - return true; -} - -enum -{ - kpidSectAlign = kpidUserDefined, - kpidFileAlign, - kpidLinkerVer, - kpidOsVer, - kpidImageVer, - kpidSubsysVer, - kpidCodeSize, - kpidImageSize, - kpidInitDataSize, - kpidUnInitDataSize, - kpidHeadersSizeUnInitDataSize, - kpidSubSystem, - kpidDllCharacts, - kpidStackReserve, - kpidStackCommit, - kpidHeapReserve, - kpidHeapCommit, - kpidImageBase - // kpidAddressOfEntryPoint, - // kpidBaseOfCode, - // kpidBaseOfData32, -}; - -STATPROPSTG kArcProps[] = -{ - { NULL, kpidCpu, VT_BSTR}, - { NULL, kpidBit64, VT_BOOL}, - { NULL, kpidCharacts, VT_BSTR}, - { NULL, kpidCTime, VT_FILETIME}, - { NULL, kpidPhySize, VT_UI4}, - { NULL, kpidHeadersSize, VT_UI4}, - { NULL, kpidChecksum, VT_UI4}, - { L"Image Size", kpidImageSize, VT_UI4}, - { L"Section Alignment", kpidSectAlign, VT_UI4}, - { L"File Alignment", kpidFileAlign, VT_UI4}, - { L"Code Size", kpidCodeSize, VT_UI4}, - { L"Initialized Data Size", kpidInitDataSize, VT_UI4}, - { L"Uninitialized Data Size", kpidUnInitDataSize, VT_UI4}, - { L"Linker Version", kpidLinkerVer, VT_BSTR}, - { L"OS Version", kpidOsVer, VT_BSTR}, - { L"Image Version", kpidImageVer, VT_BSTR}, - { L"Subsystem Version", kpidSubsysVer, VT_BSTR}, - { L"Subsystem", kpidSubSystem, VT_BSTR}, - { L"DLL Characteristics", kpidDllCharacts, VT_BSTR}, - { L"Stack Reserve", kpidStackReserve, VT_UI8}, - { L"Stack Commit", kpidStackCommit, VT_UI8}, - { L"Heap Reserve", kpidHeapReserve, VT_UI8}, - { L"Heap Commit", kpidHeapCommit, VT_UI8}, - { L"Image Base", kpidImageBase, VT_UI8} - // { L"Address Of Entry Point", kpidAddressOfEntryPoint, VT_UI8}, - // { L"Base Of Code", kpidBaseOfCode, VT_UI8}, - // { L"Base Of Data", kpidBaseOfData32, VT_UI8}, -}; - -STATPROPSTG kProps[] = -{ - { NULL, kpidPath, VT_BSTR}, - { NULL, kpidSize, VT_UI8}, - { NULL, kpidPackSize, VT_UI8}, - { NULL, kpidCharacts, VT_BSTR}, - { NULL, kpidOffset, VT_UI8}, - { NULL, kpidVa, VT_UI8} -}; - -IMP_IInArchive_Props -IMP_IInArchive_ArcProps_WITH_NAME - -static void VerToProp(const CVersion &v, NCOM::CPropVariant &prop) -{ - StringToProp(v.GetString(), prop); -} - -void TimeToProp(UInt32 unixTime, NCOM::CPropVariant &prop) -{ - if (unixTime != 0) - { - FILETIME ft; - NTime::UnixTimeToFileTime(unixTime, ft); - prop = ft; - } -} - -STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) -{ - COM_TRY_BEGIN - NCOM::CPropVariant prop; - switch(propID) - { - case kpidSectAlign: prop = _optHeader.SectAlign; break; - case kpidFileAlign: prop = _optHeader.FileAlign; break; - case kpidLinkerVer: - { - CVersion v = { _optHeader.LinkerVerMajor, _optHeader.LinkerVerMinor }; - VerToProp(v, prop); - break; - } - - case kpidOsVer: VerToProp(_optHeader.OsVer, prop); break; - case kpidImageVer: VerToProp(_optHeader.ImageVer, prop); break; - case kpidSubsysVer: VerToProp(_optHeader.SubsysVer, prop); break; - case kpidCodeSize: prop = _optHeader.CodeSize; break; - case kpidInitDataSize: prop = _optHeader.InitDataSize; break; - case kpidUnInitDataSize: prop = _optHeader.UninitDataSize; break; - case kpidImageSize: prop = _optHeader.ImageSize; break; - case kpidPhySize: prop = _totalSize; break; - case kpidHeadersSize: prop = _optHeader.HeadersSize; break; - case kpidChecksum: prop = _optHeader.CheckSum; break; - - case kpidCpu: PAIR_TO_PROP(g_MachinePairs, _header.Machine, prop); break; - case kpidBit64: if (_optHeader.Is64Bit()) prop = true; break; - case kpidSubSystem: PAIR_TO_PROP(g_SubSystems, _optHeader.SubSystem, prop); break; - - case kpidMTime: - case kpidCTime: TimeToProp(_header.Time, prop); break; - case kpidCharacts: FLAGS_TO_PROP(g_HeaderCharacts, _header.Flags, prop); break; - case kpidDllCharacts: FLAGS_TO_PROP(g_DllCharacts, _optHeader.DllCharacts, prop); break; - case kpidStackReserve: prop = _optHeader.StackReserve; break; - case kpidStackCommit: prop = _optHeader.StackCommit; break; - case kpidHeapReserve: prop = _optHeader.HeapReserve; break; - case kpidHeapCommit: prop = _optHeader.HeapCommit; break; - - case kpidImageBase: prop = _optHeader.ImageBase; break; - // case kpidAddressOfEntryPoint: prop = _optHeader.AddressOfEntryPoint; break; - // case kpidBaseOfCode: prop = _optHeader.BaseOfCode; break; - // case kpidBaseOfData32: if (!_optHeader.Is64Bit()) prop = _optHeader.BaseOfData32; break; - - case kpidMainSubfile: if (_mainSubfile >= 0) prop = (UInt32)_mainSubfile; break; - } - prop.Detach(value); - return S_OK; - COM_TRY_END -} - -void CHandler::AddResNameToString(UString &s, UInt32 id) const -{ - if ((id & kFlag) != 0) - { - UString name; - if (ReadString(id & kMask, name) == S_OK) - { - if (name.IsEmpty()) - s += L"[]"; - else - { - if (name.Length() > 1 && name[0] == '"' && name.Back() == '"') - name = name.Mid(1, name.Length() - 2); - s += name; - } - return; - } - } - wchar_t sz[32]; - ConvertUInt32ToString(id, sz); - s += sz; -} - -UString CHandler::GetLangPrefix(UInt32 lang) -{ - UString s = _resourceFileName; - s += WCHAR_PATH_SEPARATOR; - if (!_oneLang) - { - AddResNameToString(s, lang); - s += WCHAR_PATH_SEPARATOR; - } - return s; -} - -STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) -{ - COM_TRY_BEGIN - NCOM::CPropVariant prop; - const CMixItem &mixItem = _mixItems[index]; - if (mixItem.StringIndex >= 0) - { - const CStringItem &item = _strings[mixItem.StringIndex]; - switch(propID) - { - case kpidPath: prop = GetLangPrefix(item.Lang) + L"string.txt"; break; - case kpidSize: - case kpidPackSize: - prop = (UInt64)item.Size; break; - } - } - else if (mixItem.ResourceIndex < 0) - { - const CSection &item = _sections[mixItem.SectionIndex]; - switch(propID) - { - case kpidPath: StringToProp(item.Name, prop); break; - case kpidSize: prop = (UInt64)item.VSize; break; - case kpidPackSize: prop = (UInt64)item.GetPackSize(); break; - case kpidOffset: prop = item.Pa; break; - case kpidVa: if (item.IsRealSect) prop = item.Va; break; - case kpidMTime: - case kpidCTime: - TimeToProp(item.IsDebug ? item.Time : _header.Time, prop); break; - case kpidCharacts: if (item.IsRealSect) FLAGS_TO_PROP(g_SectFlags, item.Flags, prop); break; - } - } - else - { - const CResItem &item = _items[mixItem.ResourceIndex]; - switch(propID) - { - case kpidPath: - { - UString s = GetLangPrefix(item.Lang); - { - const wchar_t *p = NULL; - if (item.Type < sizeof(g_ResTypes) / sizeof(g_ResTypes[0])) - p = g_ResTypes[item.Type]; - if (p != 0) - s += p; - else - AddResNameToString(s, item.Type); - } - s += WCHAR_PATH_SEPARATOR; - AddResNameToString(s, item.ID); - if (item.HeaderSize != 0) - { - if (item.IsBmp()) - s += L".bmp"; - else if (item.IsIcon()) - s += L".ico"; - } - prop = s; - break; - } - case kpidSize: prop = (UInt64)item.GetSize(); break; - case kpidPackSize: prop = (UInt64)item.Size; break; - } - } - prop.Detach(value); - return S_OK; - COM_TRY_END -} - -HRESULT CHandler::LoadDebugSections(IInStream *stream, bool &thereIsSection) -{ - thereIsSection = false; - const CDirLink &debugLink = _optHeader.DirItems[kDirLink_Debug]; - if (debugLink.Size == 0) - return S_OK; - const unsigned kEntrySize = 28; - UInt32 numItems = debugLink.Size / kEntrySize; - if (numItems * kEntrySize != debugLink.Size || numItems > 16) - return S_FALSE; - - UInt64 pa = 0; - int i; - for (i = 0; i < _sections.Size(); i++) - { - const CSection § = _sections[i]; - if (sect.Va < debugLink.Va && debugLink.Va + debugLink.Size <= sect.Va + sect.PSize) - { - pa = sect.Pa + (debugLink.Va - sect.Va); - break; - } - } - if (i == _sections.Size()) - { - return S_OK; - // Exe for ARM requires S_OK - // return S_FALSE; - } - - CByteBuffer buffer; - buffer.SetCapacity(debugLink.Size); - Byte *buf = buffer; - - RINOK(stream->Seek(pa, STREAM_SEEK_SET, NULL)); - RINOK(ReadStream_FALSE(stream, buf, debugLink.Size)); - - for (i = 0; i < (int)numItems; i++) - { - CDebugEntry de; - de.Parse(buf); - - if (de.Size == 0) - continue; - - CSection sect; - sect.Name = ".debug" + GetDecString(i); - - sect.IsDebug = true; - sect.Time = de.Time; - sect.Va = de.Va; - sect.Pa = de.Pa; - sect.PSize = sect.VSize = de.Size; - UInt32 totalSize = sect.Pa + sect.PSize; - if (totalSize > _totalSize) - { - _totalSize = totalSize; - _sections.Add(sect); - thereIsSection = true; - } - buf += kEntrySize; - } - - return S_OK; -} - -HRESULT CHandler::ReadString(UInt32 offset, UString &dest) const -{ - if ((offset & 1) != 0 || offset >= _buf.GetCapacity()) - return S_FALSE; - size_t rem = _buf.GetCapacity() - offset; - if (rem < 2) - return S_FALSE; - unsigned length = Get16(_buf + offset); - if ((rem - 2) / 2 < length) - return S_FALSE; - dest.Empty(); - offset += 2; - for (unsigned i = 0; i < length; i++) - dest += (wchar_t)Get16(_buf + offset + i * 2); - return S_OK; -} - -HRESULT CHandler::ReadTable(UInt32 offset, CRecordVector<CTableItem> &items) -{ - if ((offset & 3) != 0 || offset >= _buf.GetCapacity()) - return S_FALSE; - size_t rem = _buf.GetCapacity() - offset; - if (rem < 16) - return S_FALSE; - items.Clear(); - unsigned numNameItems = Get16(_buf + offset + 12); - unsigned numIdItems = Get16(_buf + offset + 14); - unsigned numItems = numNameItems + numIdItems; - if ((rem - 16) / 8 < numItems) - return S_FALSE; - if (!_usedRes.SetRange(offset, 16 + numItems * 8)) - return S_FALSE; - offset += 16; - _oneLang = true; - unsigned i; - for (i = 0; i < numItems; i++) - { - CTableItem item; - const Byte *buf = _buf + offset; - offset += 8; - item.ID = Get32(buf + 0); - if (((item.ID & kFlag) != 0) != (i < numNameItems)) - return S_FALSE; - item.Offset = Get32(buf + 4); - items.Add(item); - } - return S_OK; -} - -static const UInt32 kFileSizeMax = (UInt32)1 << 30; -static const int kNumResItemsMax = (UInt32)1 << 23; -static const int kNumStringLangsMax = 128; - -// BITMAPINFOHEADER -struct CBitmapInfoHeader -{ - // UInt32 HeaderSize; - UInt32 XSize; - Int32 YSize; - UInt16 Planes; - UInt16 BitCount; - UInt32 Compression; - UInt32 SizeImage; - - bool Parse(const Byte *p, size_t size); -}; - -static const UInt32 kBitmapInfoHeader_Size = 0x28; - -bool CBitmapInfoHeader::Parse(const Byte *p, size_t size) -{ - if (size < kBitmapInfoHeader_Size || Get32(p) != kBitmapInfoHeader_Size) - return false; - XSize = Get32(p + 4); - YSize = (Int32)Get32(p + 8); - Planes = Get16(p + 12); - BitCount = Get16(p + 14); - Compression = Get32(p + 16); - SizeImage = Get32(p + 20); - return true; -} - -static UInt32 GetImageSize(UInt32 xSize, UInt32 ySize, UInt32 bitCount) -{ - return ((xSize * bitCount + 7) / 8 + 3) / 4 * 4 * ySize; -} - -static UInt32 SetBitmapHeader(Byte *dest, const Byte *src, UInt32 size) -{ - CBitmapInfoHeader h; - if (!h.Parse(src, size)) - return 0; - if (h.YSize < 0) - h.YSize = -h.YSize; - if (h.XSize > (1 << 26) || h.YSize > (1 << 26) || h.Planes != 1 || h.BitCount > 32 || - h.Compression != 0) // BI_RGB - return 0; - if (h.SizeImage == 0) - h.SizeImage = GetImageSize(h.XSize, h.YSize, h.BitCount); - UInt32 totalSize = kBmpHeaderSize + size; - UInt32 offBits = totalSize - h.SizeImage; - // BITMAPFILEHEADER - SetUi16(dest, 0x4D42); - SetUi32(dest + 2, totalSize); - SetUi32(dest + 6, 0); - SetUi32(dest + 10, offBits); - return kBmpHeaderSize; -} - -static UInt32 SetIconHeader(Byte *dest, const Byte *src, UInt32 size) -{ - CBitmapInfoHeader h; - if (!h.Parse(src, size)) - return 0; - if (h.YSize < 0) - h.YSize = -h.YSize; - if (h.XSize > (1 << 26) || h.YSize > (1 << 26) || h.Planes != 1 || - h.Compression != 0) // BI_RGB - return 0; - - UInt32 numBitCount = h.BitCount; - if (numBitCount != 1 && - numBitCount != 4 && - numBitCount != 8 && - numBitCount != 24 && - numBitCount != 32) - return 0; - - if ((h.YSize & 1) != 0) - return 0; - h.YSize /= 2; - if (h.XSize > 0x100 || h.YSize > 0x100) - return 0; - - UInt32 imageSize; - // imageSize is not correct if AND mask array contains zeros - // in this case it is equal image1Size - - // UInt32 imageSize = h.SizeImage; - // if (imageSize == 0) - // { - UInt32 image1Size = GetImageSize(h.XSize, h.YSize, h.BitCount); - UInt32 image2Size = GetImageSize(h.XSize, h.YSize, 1); - imageSize = image1Size + image2Size; - // } - UInt32 numColors = 0; - if (numBitCount < 16) - numColors = 1 << numBitCount; - - SetUi16(dest, 0); // Reserved - SetUi16(dest + 2, 1); // RES_ICON - SetUi16(dest + 4, 1); // ResCount - - dest[6] = (Byte)h.XSize; // Width - dest[7] = (Byte)h.YSize; // Height - dest[8] = (Byte)numColors; // ColorCount - dest[9] = 0; // Reserved - - SetUi32(dest + 10, 0); // Reserved1 / Reserved2 - - UInt32 numQuadsBytes = numColors * 4; - UInt32 BytesInRes = kBitmapInfoHeader_Size + numQuadsBytes + imageSize; - SetUi32(dest + 14, BytesInRes); - SetUi32(dest + 18, kIconHeaderSize); - - /* - Description = DWORDToString(xSize) + - kDelimiterChar + DWORDToString(ySize) + - kDelimiterChar + DWORDToString(numBitCount); - */ - return kIconHeaderSize; -} - -bool CHandler::ParseStringRes(UInt32 id, UInt32 lang, const Byte *src, UInt32 size) -{ - if ((size & 1) != 0) - return false; - - int i; - for (i = 0; i < _strings.Size(); i++) - if (_strings[i].Lang == lang) - break; - if (i == _strings.Size()) - { - if (_strings.Size() >= kNumStringLangsMax) - return false; - CStringItem item; - item.Size = 0; - item.Lang = lang; - i = _strings.Add(item); - } - - CStringItem &item = _strings[i]; - id = (id - 1) << 4; - UInt32 pos = 0; - for (i = 0; i < 16; i++) - { - if (size - pos < 2) - return false; - UInt32 len = Get16(src + pos); - pos += 2; - if (len != 0) - { - if (size - pos < len * 2) - return false; - char temp[32]; - ConvertUInt32ToString(id + i, temp); - size_t tempLen = strlen(temp); - size_t j; - for (j = 0; j < tempLen; j++) - item.AddChar(temp[j]); - item.AddChar('\t'); - for (j = 0; j < len; j++, pos += 2) - item.AddWChar(Get16(src + pos)); - item.AddChar(0x0D); - item.AddChar(0x0A); - } - } - return (size == pos); -} - -HRESULT CHandler::OpenResources(int sectionIndex, IInStream *stream, IArchiveOpenCallback *callback) -{ - const CSection § = _sections[sectionIndex]; - size_t fileSize = sect.PSize; // Maybe we need sect.VSize here !!! - if (fileSize > kFileSizeMax) - return S_FALSE; - { - UInt64 fileSize64 = fileSize; - if (callback) - RINOK(callback->SetTotal(NULL, &fileSize64)); - RINOK(stream->Seek(sect.Pa, STREAM_SEEK_SET, NULL)); - _buf.SetCapacity(fileSize); - for (size_t pos = 0; pos < fileSize;) - { - UInt64 offset64 = pos; - if (callback) - RINOK(callback->SetCompleted(NULL, &offset64)) - size_t rem = MyMin(fileSize - pos, (size_t)(1 << 20)); - RINOK(ReadStream_FALSE(stream, _buf + pos, rem)); - pos += rem; - } - } - - _usedRes.Alloc(fileSize); - CRecordVector<CTableItem> specItems; - RINOK(ReadTable(0, specItems)); - - _oneLang = true; - bool stringsOk = true; - size_t maxOffset = 0; - for (int i = 0; i < specItems.Size(); i++) - { - const CTableItem &item1 = specItems[i]; - if ((item1.Offset & kFlag) == 0) - return S_FALSE; - - CRecordVector<CTableItem> specItems2; - RINOK(ReadTable(item1.Offset & kMask, specItems2)); - - for (int j = 0; j < specItems2.Size(); j++) - { - const CTableItem &item2 = specItems2[j]; - if ((item2.Offset & kFlag) == 0) - return S_FALSE; - - CRecordVector<CTableItem> specItems3; - RINOK(ReadTable(item2.Offset & kMask, specItems3)); - - CResItem item; - item.Type = item1.ID; - item.ID = item2.ID; - - for (int k = 0; k < specItems3.Size(); k++) - { - if (_items.Size() >= kNumResItemsMax) - return S_FALSE; - const CTableItem &item3 = specItems3[k]; - if ((item3.Offset & kFlag) != 0) - return S_FALSE; - if (item3.Offset >= _buf.GetCapacity() || _buf.GetCapacity() - item3.Offset < 16) - return S_FALSE; - const Byte *buf = _buf + item3.Offset; - item.Lang = item3.ID; - item.Offset = Get32(buf + 0); - item.Size = Get32(buf + 4); - // UInt32 codePage = Get32(buf + 8); - if (Get32(buf + 12) != 0) - return S_FALSE; - if (!_items.IsEmpty() && _oneLang && !item.IsNameEqual(_items.Back())) - _oneLang = false; - - item.HeaderSize = 0; - - size_t offset = item.Offset - sect.Va; - if (offset > maxOffset) - maxOffset = offset; - if (offset + item.Size > maxOffset) - maxOffset = offset + item.Size; - - if (CheckItem(sect, item, offset)) - { - const Byte *data = _buf + offset; - if (item.IsBmp()) - item.HeaderSize = SetBitmapHeader(item.Header, data, item.Size); - else if (item.IsIcon()) - item.HeaderSize = SetIconHeader(item.Header, data, item.Size); - else if (item.IsString()) - { - if (stringsOk) - stringsOk = ParseStringRes(item.ID, item.Lang, data, item.Size); - } - } - - item.Enabled = true; - _items.Add(item); - } - } - } - - if (stringsOk && !_strings.IsEmpty()) - { - int i; - for (i = 0; i < _items.Size(); i++) - { - CResItem &item = _items[i]; - if (item.IsString()) - item.Enabled = false; - } - for (i = 0; i < _strings.Size(); i++) - { - if (_strings[i].Size == 0) - continue; - CMixItem mixItem; - mixItem.ResourceIndex = -1; - mixItem.StringIndex = i; - mixItem.SectionIndex = sectionIndex; - _mixItems.Add(mixItem); - } - } - - _usedRes.Free(); - - int numBits = _optHeader.GetNumFileAlignBits(); - if (numBits >= 0) - { - UInt32 mask = (1 << numBits) - 1; - size_t end = ((maxOffset + mask) & ~mask); - if (end < sect.VSize && end <= sect.PSize) - { - CSection sect2; - sect2.Flags = 0; - - // we skip Zeros to start of aligned block - size_t i; - for (i = maxOffset; i < end; i++) - if (_buf[i] != 0) - break; - if (i == end) - maxOffset = end; - - sect2.Pa = sect.Pa + (UInt32)maxOffset; - sect2.Va = sect.Va + (UInt32)maxOffset; - sect2.PSize = sect.VSize - (UInt32)maxOffset; - sect2.VSize = sect2.PSize; - sect2.Name = ".rsrc_1"; - sect2.Time = 0; - sect2.IsAdditionalSection = true; - _sections.Add(sect2); - } - } - - return S_OK; -} - -HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) -{ - const UInt32 kBufSize = 1 << 18; - const UInt32 kSigSize = 2; - - _mainSubfile = -1; - - CByteBuffer buffer; - buffer.SetCapacity(kBufSize); - Byte *buf = buffer; - - size_t processed = kSigSize; - RINOK(ReadStream_FALSE(stream, buf, processed)); - if (buf[0] != 'M' || buf[1] != 'Z') - return S_FALSE; - processed = kBufSize - kSigSize; - RINOK(ReadStream(stream, buf + kSigSize, &processed)); - processed += kSigSize; - if (!Parse(buf, (UInt32)processed)) - return S_FALSE; - bool thereISDebug; - RINOK(LoadDebugSections(stream, thereISDebug)); - - const CDirLink &certLink = _optHeader.DirItems[kDirLink_Certificate]; - if (certLink.Size != 0) - { - CSection sect; - sect.Name = "CERTIFICATE"; - sect.Va = 0; - sect.Pa = certLink.Va; - sect.PSize = sect.VSize = certLink.Size; - sect.UpdateTotalSize(_totalSize); - _sections.Add(sect); - } - - if (thereISDebug) - { - const UInt32 kAlign = 1 << 12; - UInt32 alignPos = _totalSize & (kAlign - 1); - if (alignPos != 0) - { - UInt32 size = kAlign - alignPos; - RINOK(stream->Seek(_totalSize, STREAM_SEEK_SET, NULL)); - buffer.Free(); - buffer.SetCapacity(kAlign); - Byte *buf = buffer; - size_t processed = size; - RINOK(ReadStream(stream, buf, &processed)); - size_t i; - for (i = 0; i < processed; i++) - { - if (buf[i] != 0) - break; - } - if (processed < size && processed < 100) - _totalSize += (UInt32)processed; - else if (((_totalSize + i) & 0x1FF) == 0 || processed < size) - _totalSize += (UInt32)i; - } - } - - if (_header.NumSymbols > 0 && _header.PointerToSymbolTable >= 512) - { - if (_header.NumSymbols >= (1 << 24)) - return S_FALSE; - CSection sect; - sect.Name = "COFF_SYMBOLS"; - UInt32 size = _header.NumSymbols * 18; - RINOK(stream->Seek((UInt64)_header.PointerToSymbolTable + size, STREAM_SEEK_SET, NULL)); - Byte buf[4]; - RINOK(ReadStream_FALSE(stream, buf, 4)); - UInt32 size2 = Get32(buf); - if (size2 >= (1 << 28)) - return S_FALSE; - size += size2; - - sect.Va = 0; - sect.Pa = _header.PointerToSymbolTable; - sect.PSize = sect.VSize = size; - sect.UpdateTotalSize(_totalSize); - _sections.Add(sect); - } - - UInt64 fileSize; - RINOK(stream->Seek(0, STREAM_SEEK_END, &fileSize)); - if (fileSize > _totalSize) - return S_FALSE; - _totalSizeLimited = (_totalSize < fileSize) ? _totalSize : (UInt32)fileSize; - - { - CObjectVector<CSection> sections = _sections; - sections.Sort(); - UInt32 limit = (1 << 12); - int num = 0; - int numSections = sections.Size(); - for (int i = 0; i < numSections; i++) - { - const CSection &s = sections[i]; - if (s.Pa > limit) - { - CSection s2; - s2.Pa = s2.Va = limit; - s2.PSize = s2.VSize = s.Pa - limit; - s2.IsAdditionalSection = true; - s2.Name = '['; - s2.Name += GetDecString(num++); - s2.Name += ']'; - _sections.Add(s2); - limit = s.Pa; - } - UInt32 next = s.Pa + s.PSize; - if (next < s.Pa) - break; - if (next >= limit) - limit = next; - } - } - - _parseResources = true; - - UInt64 mainSize = 0, mainSize2 = 0; - int i; - for (i = 0; i < _sections.Size(); i++) - { - const CSection § = _sections[i]; - CMixItem mixItem; - mixItem.SectionIndex = i; - if (_parseResources && sect.Name == ".rsrc" && _items.IsEmpty()) - { - HRESULT res = OpenResources(i, stream, callback); - if (res == S_OK) - { - _resourceFileName = GetUnicodeString(sect.Name); - for (int j = 0; j < _items.Size(); j++) - { - const CResItem &item = _items[j]; - if (item.Enabled) - { - mixItem.ResourceIndex = j; - mixItem.StringIndex = -1; - if (item.IsRcDataOrUnknown()) - { - if (item.Size >= mainSize) - { - mainSize2 = mainSize; - mainSize = item.Size; - _mainSubfile = _mixItems.Size(); - } - else if (item.Size >= mainSize2) - mainSize2 = item.Size; - } - _mixItems.Add(mixItem); - } - } - if (sect.PSize > sect.VSize) - { - int numBits = _optHeader.GetNumFileAlignBits(); - if (numBits >= 0) - { - UInt32 mask = (1 << numBits) - 1; - UInt32 end = ((sect.VSize + mask) & ~mask); - - if (sect.PSize > end) - { - CSection sect2; - sect2.Flags = 0; - sect2.Pa = sect.Pa + end; - sect2.Va = sect.Va + end; - sect2.PSize = sect.PSize - end; - sect2.VSize = sect2.PSize; - sect2.Name = ".rsrc_2"; - sect2.Time = 0; - sect2.IsAdditionalSection = true; - _sections.Add(sect2); - } - } - } - continue; - } - if (res != S_FALSE) - return res; - CloseResources(); - } - mixItem.StringIndex = -1; - mixItem.ResourceIndex = -1; - if (sect.IsAdditionalSection) - { - if (sect.PSize >= mainSize) - { - mainSize2 = mainSize; - mainSize = sect.PSize; - _mainSubfile = _mixItems.Size(); - } - else - mainSize2 = sect.PSize; - } - _mixItems.Add(mixItem); - } - - if (mainSize2 >= (1 << 20) && mainSize < mainSize2 * 2) - _mainSubfile = -1; - - for (i = 0; i < _mixItems.Size(); i++) - { - const CMixItem &mixItem = _mixItems[i]; - if (mixItem.StringIndex < 0 && mixItem.ResourceIndex < 0 && _sections[mixItem.SectionIndex].Name == "_winzip_") - { - _mainSubfile = i; - break; - } - } - - return S_OK; -} - -HRESULT CalcCheckSum(ISequentialInStream *stream, UInt32 size, UInt32 excludePos, UInt32 &res) -{ - // size &= ~1; - const UInt32 kBufSize = 1 << 23; - CByteBuffer buffer; - buffer.SetCapacity(kBufSize); - Byte *buf = buffer; - - UInt32 sum = 0; - UInt32 pos = 0; - for (;;) - { - UInt32 rem = size - pos; - if (rem > kBufSize) - rem = kBufSize; - if (rem == 0) - break; - size_t processed = rem; - RINOK(ReadStream(stream, buf, &processed)); - - /* - for (; processed < rem; processed++) - buf[processed] = 0; - */ - - if ((processed & 1) != 0) - buf[processed] = 0; - - for (int j = 0; j < 4; j++) - { - UInt32 p = excludePos + j; - if (pos <= p && p < pos + processed) - buf[p - pos] = 0; - } - - for (size_t i = 0; i < processed; i += 2) - { - sum += Get16(buf + i); - sum = (sum + (sum >> 16)) & 0xFFFF; - } - pos += (UInt32)processed; - if (rem != processed) - break; - } - sum += pos; - res = sum; - return S_OK; -} - -STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *callback) -{ - COM_TRY_BEGIN - Close(); - RINOK(Open2(inStream, callback)); - _stream = inStream; - return S_OK; - COM_TRY_END -} - -void CHandler::CloseResources() -{ - _usedRes.Free(); - _items.Clear(); - _strings.Clear(); - _buf.SetCapacity(0); -} - -STDMETHODIMP CHandler::Close() -{ - _stream.Release(); - _sections.Clear(); - _mixItems.Clear(); - CloseResources(); - return S_OK; -} - -STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) -{ - *numItems = _mixItems.Size(); - return S_OK; -} - -STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, - Int32 testMode, IArchiveExtractCallback *extractCallback) -{ - COM_TRY_BEGIN - bool allFilesMode = (numItems == (UInt32)-1); - if (allFilesMode) - numItems = _mixItems.Size(); - if (numItems == 0) - return S_OK; - UInt64 totalSize = 0; - UInt32 i; - for (i = 0; i < numItems; i++) - { - const CMixItem &mixItem = _mixItems[allFilesMode ? i : indices[i]]; - if (mixItem.StringIndex >= 0) - totalSize += _strings[mixItem.StringIndex].Size; - else if (mixItem.ResourceIndex < 0) - totalSize += _sections[mixItem.SectionIndex].GetPackSize(); - else - totalSize += _items[mixItem.ResourceIndex].GetSize(); - } - extractCallback->SetTotal(totalSize); - - UInt64 currentTotalSize = 0; - UInt64 currentItemSize; - - NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); - CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; - - CLocalProgress *lps = new CLocalProgress; - CMyComPtr<ICompressProgressInfo> progress = lps; - lps->Init(extractCallback, false); - - bool checkSumOK = true; - if (_optHeader.CheckSum != 0 && (int)numItems == _mixItems.Size()) - { - UInt32 checkSum = 0; - RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL)); - CalcCheckSum(_stream, _totalSizeLimited, _peOffset + kHeaderSize + 64, checkSum); - checkSumOK = (checkSum == _optHeader.CheckSum); - } - - CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; - CMyComPtr<ISequentialInStream> inStream(streamSpec); - streamSpec->SetStream(_stream); - - for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize) - { - lps->InSize = lps->OutSize = currentTotalSize; - RINOK(lps->SetCur()); - Int32 askMode = testMode ? - NExtract::NAskMode::kTest : - NExtract::NAskMode::kExtract; - UInt32 index = allFilesMode ? i : indices[i]; - - CMyComPtr<ISequentialOutStream> outStream; - RINOK(extractCallback->GetStream(index, &outStream, askMode)); - const CMixItem &mixItem = _mixItems[index]; - - const CSection § = _sections[mixItem.SectionIndex]; - bool isOk = true; - if (mixItem.StringIndex >= 0) - { - const CStringItem &item = _strings[mixItem.StringIndex]; - currentItemSize = item.Size; - if (!testMode && !outStream) - continue; - - RINOK(extractCallback->PrepareOperation(askMode)); - if (outStream) - RINOK(WriteStream(outStream, item.Buf, item.Size)); - } - else if (mixItem.ResourceIndex < 0) - { - currentItemSize = sect.GetPackSize(); - if (!testMode && !outStream) - continue; - - RINOK(extractCallback->PrepareOperation(askMode)); - RINOK(_stream->Seek(sect.Pa, STREAM_SEEK_SET, NULL)); - streamSpec->Init(currentItemSize); - RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)); - isOk = (copyCoderSpec->TotalSize == currentItemSize); - } - else - { - const CResItem &item = _items[mixItem.ResourceIndex]; - currentItemSize = item.GetSize(); - if (!testMode && !outStream) - continue; - - RINOK(extractCallback->PrepareOperation(askMode)); - size_t offset = item.Offset - sect.Va; - if (!CheckItem(sect, item, offset)) - isOk = false; - else if (outStream) - { - if (item.HeaderSize != 0) - RINOK(WriteStream(outStream, item.Header, item.HeaderSize)); - RINOK(WriteStream(outStream, _buf + offset, item.Size)); - } - } - - outStream.Release(); - RINOK(extractCallback->SetOperationResult(isOk ? - checkSumOK ? - NExtract::NOperationResult::kOK: - NExtract::NOperationResult::kCRCError: - NExtract::NOperationResult::kDataError)); - } - return S_OK; - COM_TRY_END -} - -STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) -{ - COM_TRY_BEGIN - *stream = 0; - - const CMixItem &mixItem = _mixItems[index]; - const CSection § = _sections[mixItem.SectionIndex]; - if (mixItem.IsSectionItem()) - return CreateLimitedInStream(_stream, sect.Pa, sect.PSize, stream); - - CBufInStream *inStreamSpec = new CBufInStream; - CMyComPtr<ISequentialInStream> streamTemp = inStreamSpec; - CReferenceBuf *referenceBuf = new CReferenceBuf; - CMyComPtr<IUnknown> ref = referenceBuf; - if (mixItem.StringIndex >= 0) - { - const CStringItem &item = _strings[mixItem.StringIndex]; - referenceBuf->Buf.SetCapacity(item.Size); - memcpy(referenceBuf->Buf, item.Buf, item.Size); - } - else - { - const CResItem &item = _items[mixItem.ResourceIndex]; - size_t offset = item.Offset - sect.Va; - if (!CheckItem(sect, item, offset)) - return S_FALSE; - if (item.HeaderSize == 0) - { - CBufInStream *streamSpec = new CBufInStream; - CMyComPtr<IInStream> streamTemp2 = streamSpec; - streamSpec->Init(_buf + offset, item.Size, (IInArchive *)this); - *stream = streamTemp2.Detach(); - return S_OK; - } - referenceBuf->Buf.SetCapacity(item.HeaderSize + item.Size); - memcpy(referenceBuf->Buf, item.Header, item.HeaderSize); - memcpy(referenceBuf->Buf + item.HeaderSize, _buf + offset, item.Size); - } - inStreamSpec->Init(referenceBuf); - - *stream = streamTemp.Detach(); - return S_OK; - COM_TRY_END -} - -static IInArchive *CreateArc() { return new CHandler; } - -static CArcInfo g_ArcInfo = - { L"PE", L"exe dll sys", 0, 0xDD, { 'P', 'E', 0, 0 }, 4, false, CreateArc, 0 }; - -REGISTER_ARC(Pe) - -}} |