1*f6dc9357SAndroid Build Coastguard Worker // PeHandler.cpp
2*f6dc9357SAndroid Build Coastguard Worker
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker
5*f6dc9357SAndroid Build Coastguard Worker // #include <stdio.h>
6*f6dc9357SAndroid Build Coastguard Worker
7*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/CpuArch.h"
8*f6dc9357SAndroid Build Coastguard Worker
9*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/DynamicBuffer.h"
10*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/ComTry.h"
11*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/IntToString.h"
12*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/StringConvert.h"
13*f6dc9357SAndroid Build Coastguard Worker
14*f6dc9357SAndroid Build Coastguard Worker #include "../../Windows/PropVariantUtils.h"
15*f6dc9357SAndroid Build Coastguard Worker #include "../../Windows/TimeUtils.h"
16*f6dc9357SAndroid Build Coastguard Worker
17*f6dc9357SAndroid Build Coastguard Worker #include "../Common/LimitedStreams.h"
18*f6dc9357SAndroid Build Coastguard Worker #include "../Common/ProgressUtils.h"
19*f6dc9357SAndroid Build Coastguard Worker #include "../Common/RegisterArc.h"
20*f6dc9357SAndroid Build Coastguard Worker #include "../Common/StreamObjects.h"
21*f6dc9357SAndroid Build Coastguard Worker #include "../Common/StreamUtils.h"
22*f6dc9357SAndroid Build Coastguard Worker
23*f6dc9357SAndroid Build Coastguard Worker #include "../Compress/CopyCoder.h"
24*f6dc9357SAndroid Build Coastguard Worker
25*f6dc9357SAndroid Build Coastguard Worker #define Get16(p) GetUi16(p)
26*f6dc9357SAndroid Build Coastguard Worker #define Get32(p) GetUi32(p)
27*f6dc9357SAndroid Build Coastguard Worker #define Get64(p) GetUi64(p)
28*f6dc9357SAndroid Build Coastguard Worker
29*f6dc9357SAndroid Build Coastguard Worker #define G16(offs, v) v = Get16(p + (offs))
30*f6dc9357SAndroid Build Coastguard Worker #define G32(offs, v) v = Get32(p + (offs))
31*f6dc9357SAndroid Build Coastguard Worker #define G32_signed(offs, v) v = (Int32)Get32(p + (offs))
32*f6dc9357SAndroid Build Coastguard Worker #define G64(offs, v) v = Get64(p + (offs))
33*f6dc9357SAndroid Build Coastguard Worker
34*f6dc9357SAndroid Build Coastguard Worker #define RINOZ(x) { int _tt_ = (x); if (_tt_ != 0) return _tt_; }
35*f6dc9357SAndroid Build Coastguard Worker
36*f6dc9357SAndroid Build Coastguard Worker using namespace NWindows;
37*f6dc9357SAndroid Build Coastguard Worker
38*f6dc9357SAndroid Build Coastguard Worker namespace NArchive {
39*f6dc9357SAndroid Build Coastguard Worker namespace NPe {
40*f6dc9357SAndroid Build Coastguard Worker
41*f6dc9357SAndroid Build Coastguard Worker static const UInt32 k_Signature32 = 0x00004550;
42*f6dc9357SAndroid Build Coastguard Worker
CalcCheckSum(ISequentialInStream * stream,UInt32 size,UInt32 excludePos,UInt32 & res)43*f6dc9357SAndroid Build Coastguard Worker static HRESULT CalcCheckSum(ISequentialInStream *stream, UInt32 size, UInt32 excludePos, UInt32 &res)
44*f6dc9357SAndroid Build Coastguard Worker {
45*f6dc9357SAndroid Build Coastguard Worker const UInt32 kBufSizeMax = (UInt32)1 << 15;
46*f6dc9357SAndroid Build Coastguard Worker UInt32 bufSize = kBufSizeMax;
47*f6dc9357SAndroid Build Coastguard Worker CByteBuffer buffer(bufSize);
48*f6dc9357SAndroid Build Coastguard Worker Byte *buf = buffer;
49*f6dc9357SAndroid Build Coastguard Worker UInt32 sum = 0;
50*f6dc9357SAndroid Build Coastguard Worker UInt32 pos = 0;
51*f6dc9357SAndroid Build Coastguard Worker for (;;)
52*f6dc9357SAndroid Build Coastguard Worker {
53*f6dc9357SAndroid Build Coastguard Worker UInt32 rem = size - pos;
54*f6dc9357SAndroid Build Coastguard Worker if (rem > bufSize)
55*f6dc9357SAndroid Build Coastguard Worker rem = bufSize;
56*f6dc9357SAndroid Build Coastguard Worker if (rem == 0)
57*f6dc9357SAndroid Build Coastguard Worker break;
58*f6dc9357SAndroid Build Coastguard Worker size_t processed = rem;
59*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream(stream, buf, &processed))
60*f6dc9357SAndroid Build Coastguard Worker
61*f6dc9357SAndroid Build Coastguard Worker for (unsigned j = 0; j < 4; j++)
62*f6dc9357SAndroid Build Coastguard Worker {
63*f6dc9357SAndroid Build Coastguard Worker UInt32 e = excludePos + j;
64*f6dc9357SAndroid Build Coastguard Worker if (pos <= e)
65*f6dc9357SAndroid Build Coastguard Worker {
66*f6dc9357SAndroid Build Coastguard Worker e -= pos;
67*f6dc9357SAndroid Build Coastguard Worker if (e < processed)
68*f6dc9357SAndroid Build Coastguard Worker buf[e] = 0;
69*f6dc9357SAndroid Build Coastguard Worker }
70*f6dc9357SAndroid Build Coastguard Worker }
71*f6dc9357SAndroid Build Coastguard Worker
72*f6dc9357SAndroid Build Coastguard Worker const unsigned kStep = (1 << 4);
73*f6dc9357SAndroid Build Coastguard Worker {
74*f6dc9357SAndroid Build Coastguard Worker for (size_t i = processed; (i & (kStep - 1)) != 0; i++)
75*f6dc9357SAndroid Build Coastguard Worker buf[i] = 0;
76*f6dc9357SAndroid Build Coastguard Worker }
77*f6dc9357SAndroid Build Coastguard Worker {
78*f6dc9357SAndroid Build Coastguard Worker const Byte *buf2 = buf;
79*f6dc9357SAndroid Build Coastguard Worker const Byte *bufLimit = buf + processed;
80*f6dc9357SAndroid Build Coastguard Worker UInt64 sum2 = 0;
81*f6dc9357SAndroid Build Coastguard Worker for (; buf2 < bufLimit; buf2 += kStep)
82*f6dc9357SAndroid Build Coastguard Worker {
83*f6dc9357SAndroid Build Coastguard Worker UInt64 sum3 = (UInt64)Get32(buf2)
84*f6dc9357SAndroid Build Coastguard Worker + Get32(buf2 + 4)
85*f6dc9357SAndroid Build Coastguard Worker + Get32(buf2 + 8)
86*f6dc9357SAndroid Build Coastguard Worker + Get32(buf2 + 12);
87*f6dc9357SAndroid Build Coastguard Worker sum2 += sum3;
88*f6dc9357SAndroid Build Coastguard Worker }
89*f6dc9357SAndroid Build Coastguard Worker sum2 = (UInt32)(sum2) + (UInt64)(sum2 >> 32);
90*f6dc9357SAndroid Build Coastguard Worker UInt32 sum3 = ((UInt32)sum2 + (UInt32)(sum2 >> 32));
91*f6dc9357SAndroid Build Coastguard Worker sum += (sum3 & 0xFFFF) + (sum3 >> 16);
92*f6dc9357SAndroid Build Coastguard Worker sum = (sum & 0xFFFF) + (sum >> 16);
93*f6dc9357SAndroid Build Coastguard Worker sum = (sum & 0xFFFF) + (sum >> 16);
94*f6dc9357SAndroid Build Coastguard Worker }
95*f6dc9357SAndroid Build Coastguard Worker
96*f6dc9357SAndroid Build Coastguard Worker pos += (UInt32)processed;
97*f6dc9357SAndroid Build Coastguard Worker if (rem != processed)
98*f6dc9357SAndroid Build Coastguard Worker break;
99*f6dc9357SAndroid Build Coastguard Worker }
100*f6dc9357SAndroid Build Coastguard Worker res = sum + pos;
101*f6dc9357SAndroid Build Coastguard Worker return S_OK;
102*f6dc9357SAndroid Build Coastguard Worker }
103*f6dc9357SAndroid Build Coastguard Worker
104*f6dc9357SAndroid Build Coastguard Worker
105*f6dc9357SAndroid Build Coastguard Worker struct CVersion
106*f6dc9357SAndroid Build Coastguard Worker {
107*f6dc9357SAndroid Build Coastguard Worker UInt16 Major;
108*f6dc9357SAndroid Build Coastguard Worker UInt16 Minor;
109*f6dc9357SAndroid Build Coastguard Worker
ParseNArchive::NPe::CVersion110*f6dc9357SAndroid Build Coastguard Worker void Parse(const Byte *p)
111*f6dc9357SAndroid Build Coastguard Worker {
112*f6dc9357SAndroid Build Coastguard Worker G16(0, Major);
113*f6dc9357SAndroid Build Coastguard Worker G16(2, Minor);
114*f6dc9357SAndroid Build Coastguard Worker }
115*f6dc9357SAndroid Build Coastguard Worker void ToProp(NCOM::CPropVariant &prop);
116*f6dc9357SAndroid Build Coastguard Worker };
117*f6dc9357SAndroid Build Coastguard Worker
ToProp(NCOM::CPropVariant & prop)118*f6dc9357SAndroid Build Coastguard Worker void CVersion::ToProp(NCOM::CPropVariant &prop)
119*f6dc9357SAndroid Build Coastguard Worker {
120*f6dc9357SAndroid Build Coastguard Worker char sz[32];
121*f6dc9357SAndroid Build Coastguard Worker ConvertUInt32ToString(Major, sz);
122*f6dc9357SAndroid Build Coastguard Worker unsigned len = MyStringLen(sz);
123*f6dc9357SAndroid Build Coastguard Worker sz[len] = '.';
124*f6dc9357SAndroid Build Coastguard Worker ConvertUInt32ToString(Minor, sz + len + 1);
125*f6dc9357SAndroid Build Coastguard Worker prop = sz;
126*f6dc9357SAndroid Build Coastguard Worker }
127*f6dc9357SAndroid Build Coastguard Worker
128*f6dc9357SAndroid Build Coastguard Worker static const unsigned kCoffHeaderSize = 20;
129*f6dc9357SAndroid Build Coastguard Worker static const unsigned kPeHeaderSize = 4 + kCoffHeaderSize;
130*f6dc9357SAndroid Build Coastguard Worker static const unsigned k_OptHeader32_Size_MIN = 96;
131*f6dc9357SAndroid Build Coastguard Worker static const unsigned k_OptHeader64_Size_MIN = 112;
132*f6dc9357SAndroid Build Coastguard Worker
133*f6dc9357SAndroid Build Coastguard Worker static const UInt32 PE_IMAGE_FILE_DLL = (1 << 13);
134*f6dc9357SAndroid Build Coastguard Worker
135*f6dc9357SAndroid Build Coastguard Worker struct CHeader
136*f6dc9357SAndroid Build Coastguard Worker {
137*f6dc9357SAndroid Build Coastguard Worker UInt16 Machine;
138*f6dc9357SAndroid Build Coastguard Worker UInt16 NumSections;
139*f6dc9357SAndroid Build Coastguard Worker UInt32 Time;
140*f6dc9357SAndroid Build Coastguard Worker UInt32 PointerToSymbolTable;
141*f6dc9357SAndroid Build Coastguard Worker UInt32 NumSymbols;
142*f6dc9357SAndroid Build Coastguard Worker UInt16 OptHeaderSize;
143*f6dc9357SAndroid Build Coastguard Worker UInt16 Flags;
144*f6dc9357SAndroid Build Coastguard Worker
145*f6dc9357SAndroid Build Coastguard Worker void ParseBase(const Byte *p);
146*f6dc9357SAndroid Build Coastguard Worker bool ParseCoff(const Byte *p);
147*f6dc9357SAndroid Build Coastguard Worker bool ParsePe(const Byte *p);
IsDllNArchive::NPe::CHeader148*f6dc9357SAndroid Build Coastguard Worker bool IsDll() const { return (Flags & PE_IMAGE_FILE_DLL) != 0; }
149*f6dc9357SAndroid Build Coastguard Worker };
150*f6dc9357SAndroid Build Coastguard Worker
ParseBase(const Byte * p)151*f6dc9357SAndroid Build Coastguard Worker void CHeader::ParseBase(const Byte *p)
152*f6dc9357SAndroid Build Coastguard Worker {
153*f6dc9357SAndroid Build Coastguard Worker G16( 0, Machine);
154*f6dc9357SAndroid Build Coastguard Worker G16( 2, NumSections);
155*f6dc9357SAndroid Build Coastguard Worker G32( 4, Time);
156*f6dc9357SAndroid Build Coastguard Worker G32( 8, PointerToSymbolTable);
157*f6dc9357SAndroid Build Coastguard Worker G32(12, NumSymbols);
158*f6dc9357SAndroid Build Coastguard Worker G16(16, OptHeaderSize);
159*f6dc9357SAndroid Build Coastguard Worker G16(18, Flags);
160*f6dc9357SAndroid Build Coastguard Worker }
161*f6dc9357SAndroid Build Coastguard Worker
ParsePe(const Byte * p)162*f6dc9357SAndroid Build Coastguard Worker bool CHeader::ParsePe(const Byte *p)
163*f6dc9357SAndroid Build Coastguard Worker {
164*f6dc9357SAndroid Build Coastguard Worker if (Get32(p) != k_Signature32)
165*f6dc9357SAndroid Build Coastguard Worker return false;
166*f6dc9357SAndroid Build Coastguard Worker ParseBase(p + 4);
167*f6dc9357SAndroid Build Coastguard Worker return OptHeaderSize >= k_OptHeader32_Size_MIN;
168*f6dc9357SAndroid Build Coastguard Worker }
169*f6dc9357SAndroid Build Coastguard Worker
170*f6dc9357SAndroid Build Coastguard Worker struct CDirLink
171*f6dc9357SAndroid Build Coastguard Worker {
172*f6dc9357SAndroid Build Coastguard Worker UInt32 Va;
173*f6dc9357SAndroid Build Coastguard Worker UInt32 Size;
174*f6dc9357SAndroid Build Coastguard Worker
CDirLinkNArchive::NPe::CDirLink175*f6dc9357SAndroid Build Coastguard Worker CDirLink(): Va(0), Size(0) {}
ParseNArchive::NPe::CDirLink176*f6dc9357SAndroid Build Coastguard Worker void Parse(const Byte *p)
177*f6dc9357SAndroid Build Coastguard Worker {
178*f6dc9357SAndroid Build Coastguard Worker G32(0, Va);
179*f6dc9357SAndroid Build Coastguard Worker G32(4, Size);
180*f6dc9357SAndroid Build Coastguard Worker }
181*f6dc9357SAndroid Build Coastguard Worker };
182*f6dc9357SAndroid Build Coastguard Worker
183*f6dc9357SAndroid Build Coastguard Worker
184*f6dc9357SAndroid Build Coastguard Worker // IMAGE_DIRECTORY_ENTRY_*
185*f6dc9357SAndroid Build Coastguard Worker static const char * const g_Dir_Names[] =
186*f6dc9357SAndroid Build Coastguard Worker {
187*f6dc9357SAndroid Build Coastguard Worker "EXPORT"
188*f6dc9357SAndroid Build Coastguard Worker , "IMPORT"
189*f6dc9357SAndroid Build Coastguard Worker , "RESOURCE"
190*f6dc9357SAndroid Build Coastguard Worker , "EXCEPTION"
191*f6dc9357SAndroid Build Coastguard Worker , "SECURITY"
192*f6dc9357SAndroid Build Coastguard Worker , "BASERELOC"
193*f6dc9357SAndroid Build Coastguard Worker , "DEBUG"
194*f6dc9357SAndroid Build Coastguard Worker , "ARCHITECTURE" // "COPYRIGHT"
195*f6dc9357SAndroid Build Coastguard Worker , "GLOBALPTR"
196*f6dc9357SAndroid Build Coastguard Worker , "TLS"
197*f6dc9357SAndroid Build Coastguard Worker , "LOAD_CONFIG"
198*f6dc9357SAndroid Build Coastguard Worker , "BOUND_IMPORT"
199*f6dc9357SAndroid Build Coastguard Worker , "IAT"
200*f6dc9357SAndroid Build Coastguard Worker , "DELAY_IMPORT"
201*f6dc9357SAndroid Build Coastguard Worker , "COM_DESCRIPTOR"
202*f6dc9357SAndroid Build Coastguard Worker };
203*f6dc9357SAndroid Build Coastguard Worker
204*f6dc9357SAndroid Build Coastguard Worker enum
205*f6dc9357SAndroid Build Coastguard Worker {
206*f6dc9357SAndroid Build Coastguard Worker kDirLink_EXCEPTION = 3,
207*f6dc9357SAndroid Build Coastguard Worker kDirLink_Certificate = 4,
208*f6dc9357SAndroid Build Coastguard Worker kDirLink_BASERELOC = 5,
209*f6dc9357SAndroid Build Coastguard Worker kDirLink_Debug = 6
210*f6dc9357SAndroid Build Coastguard Worker };
211*f6dc9357SAndroid Build Coastguard Worker
212*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kNumDirItemsMax = 16;
213*f6dc9357SAndroid Build Coastguard Worker
214*f6dc9357SAndroid Build Coastguard Worker struct CDebugEntry
215*f6dc9357SAndroid Build Coastguard Worker {
216*f6dc9357SAndroid Build Coastguard Worker UInt32 Flags;
217*f6dc9357SAndroid Build Coastguard Worker UInt32 Time;
218*f6dc9357SAndroid Build Coastguard Worker CVersion Ver;
219*f6dc9357SAndroid Build Coastguard Worker UInt32 Type;
220*f6dc9357SAndroid Build Coastguard Worker UInt32 Size;
221*f6dc9357SAndroid Build Coastguard Worker UInt32 Va;
222*f6dc9357SAndroid Build Coastguard Worker UInt32 Pa;
223*f6dc9357SAndroid Build Coastguard Worker
ParseNArchive::NPe::CDebugEntry224*f6dc9357SAndroid Build Coastguard Worker void Parse(const Byte *p)
225*f6dc9357SAndroid Build Coastguard Worker {
226*f6dc9357SAndroid Build Coastguard Worker G32(0, Flags);
227*f6dc9357SAndroid Build Coastguard Worker G32(4, Time);
228*f6dc9357SAndroid Build Coastguard Worker Ver.Parse(p + 8);
229*f6dc9357SAndroid Build Coastguard Worker G32(12, Type);
230*f6dc9357SAndroid Build Coastguard Worker G32(16, Size);
231*f6dc9357SAndroid Build Coastguard Worker G32(20, Va);
232*f6dc9357SAndroid Build Coastguard Worker G32(24, Pa);
233*f6dc9357SAndroid Build Coastguard Worker }
234*f6dc9357SAndroid Build Coastguard Worker };
235*f6dc9357SAndroid Build Coastguard Worker
236*f6dc9357SAndroid Build Coastguard Worker static const UInt32 k_CheckSum_Field_Offset = 64;
237*f6dc9357SAndroid Build Coastguard Worker
238*f6dc9357SAndroid Build Coastguard Worker static const UInt32 PE_OptHeader_Magic_32 = 0x10B;
239*f6dc9357SAndroid Build Coastguard Worker static const UInt32 PE_OptHeader_Magic_64 = 0x20B;
240*f6dc9357SAndroid Build Coastguard Worker
241*f6dc9357SAndroid Build Coastguard Worker static const UInt32 k_SubSystems_EFI_First = 10;
242*f6dc9357SAndroid Build Coastguard Worker static const UInt32 k_SubSystems_EFI_Last = 13;
243*f6dc9357SAndroid Build Coastguard Worker
244*f6dc9357SAndroid Build Coastguard Worker struct COptHeader
245*f6dc9357SAndroid Build Coastguard Worker {
246*f6dc9357SAndroid Build Coastguard Worker UInt16 Magic;
247*f6dc9357SAndroid Build Coastguard Worker Byte LinkerVerMajor;
248*f6dc9357SAndroid Build Coastguard Worker Byte LinkerVerMinor;
249*f6dc9357SAndroid Build Coastguard Worker
250*f6dc9357SAndroid Build Coastguard Worker UInt32 CodeSize;
251*f6dc9357SAndroid Build Coastguard Worker UInt32 InitDataSize;
252*f6dc9357SAndroid Build Coastguard Worker UInt32 UninitDataSize;
253*f6dc9357SAndroid Build Coastguard Worker
254*f6dc9357SAndroid Build Coastguard Worker // UInt32 AddressOfEntryPoint;
255*f6dc9357SAndroid Build Coastguard Worker // UInt32 BaseOfCode; // VA(.text) == 0x1000 in most cases
256*f6dc9357SAndroid Build Coastguard Worker // UInt32 BaseOfData32;
257*f6dc9357SAndroid Build Coastguard Worker UInt64 ImageBase;
258*f6dc9357SAndroid Build Coastguard Worker
259*f6dc9357SAndroid Build Coastguard Worker UInt32 SectAlign;
260*f6dc9357SAndroid Build Coastguard Worker UInt32 FileAlign;
261*f6dc9357SAndroid Build Coastguard Worker
262*f6dc9357SAndroid Build Coastguard Worker CVersion OsVer;
263*f6dc9357SAndroid Build Coastguard Worker CVersion ImageVer;
264*f6dc9357SAndroid Build Coastguard Worker CVersion SubsysVer;
265*f6dc9357SAndroid Build Coastguard Worker
266*f6dc9357SAndroid Build Coastguard Worker UInt32 ImageSize;
267*f6dc9357SAndroid Build Coastguard Worker UInt32 HeadersSize;
268*f6dc9357SAndroid Build Coastguard Worker UInt32 CheckSum;
269*f6dc9357SAndroid Build Coastguard Worker UInt16 SubSystem;
270*f6dc9357SAndroid Build Coastguard Worker UInt16 DllCharacts;
271*f6dc9357SAndroid Build Coastguard Worker
272*f6dc9357SAndroid Build Coastguard Worker UInt64 StackReserve;
273*f6dc9357SAndroid Build Coastguard Worker UInt64 StackCommit;
274*f6dc9357SAndroid Build Coastguard Worker UInt64 HeapReserve;
275*f6dc9357SAndroid Build Coastguard Worker UInt64 HeapCommit;
276*f6dc9357SAndroid Build Coastguard Worker
277*f6dc9357SAndroid Build Coastguard Worker UInt32 NumDirItems;
278*f6dc9357SAndroid Build Coastguard Worker CDirLink DirItems[kNumDirItemsMax];
279*f6dc9357SAndroid Build Coastguard Worker
Is64BitNArchive::NPe::COptHeader280*f6dc9357SAndroid Build Coastguard Worker bool Is64Bit() const { return Magic == PE_OptHeader_Magic_64; }
281*f6dc9357SAndroid Build Coastguard Worker bool Parse(const Byte *p, UInt32 size);
282*f6dc9357SAndroid Build Coastguard Worker
GetNumFileAlignBitsNArchive::NPe::COptHeader283*f6dc9357SAndroid Build Coastguard Worker int GetNumFileAlignBits() const
284*f6dc9357SAndroid Build Coastguard Worker {
285*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < 32; i++)
286*f6dc9357SAndroid Build Coastguard Worker if (((UInt32)1 << i) == FileAlign)
287*f6dc9357SAndroid Build Coastguard Worker return (int)i;
288*f6dc9357SAndroid Build Coastguard Worker return -1;
289*f6dc9357SAndroid Build Coastguard Worker }
290*f6dc9357SAndroid Build Coastguard Worker
IsSybSystem_EFINArchive::NPe::COptHeader291*f6dc9357SAndroid Build Coastguard Worker bool IsSybSystem_EFI() const
292*f6dc9357SAndroid Build Coastguard Worker {
293*f6dc9357SAndroid Build Coastguard Worker return
294*f6dc9357SAndroid Build Coastguard Worker SubSystem >= k_SubSystems_EFI_First &&
295*f6dc9357SAndroid Build Coastguard Worker SubSystem <= k_SubSystems_EFI_Last;
296*f6dc9357SAndroid Build Coastguard Worker }
297*f6dc9357SAndroid Build Coastguard Worker };
298*f6dc9357SAndroid Build Coastguard Worker
299*f6dc9357SAndroid Build Coastguard Worker // size is 16-bit
Parse(const Byte * p,UInt32 size)300*f6dc9357SAndroid Build Coastguard Worker bool COptHeader::Parse(const Byte *p, UInt32 size)
301*f6dc9357SAndroid Build Coastguard Worker {
302*f6dc9357SAndroid Build Coastguard Worker if (size < k_OptHeader32_Size_MIN)
303*f6dc9357SAndroid Build Coastguard Worker return false;
304*f6dc9357SAndroid Build Coastguard Worker Magic = Get16(p);
305*f6dc9357SAndroid Build Coastguard Worker switch (Magic)
306*f6dc9357SAndroid Build Coastguard Worker {
307*f6dc9357SAndroid Build Coastguard Worker case PE_OptHeader_Magic_32:
308*f6dc9357SAndroid Build Coastguard Worker case PE_OptHeader_Magic_64:
309*f6dc9357SAndroid Build Coastguard Worker break;
310*f6dc9357SAndroid Build Coastguard Worker default:
311*f6dc9357SAndroid Build Coastguard Worker return false;
312*f6dc9357SAndroid Build Coastguard Worker }
313*f6dc9357SAndroid Build Coastguard Worker LinkerVerMajor = p[2];
314*f6dc9357SAndroid Build Coastguard Worker LinkerVerMinor = p[3];
315*f6dc9357SAndroid Build Coastguard Worker
316*f6dc9357SAndroid Build Coastguard Worker G32( 4, CodeSize);
317*f6dc9357SAndroid Build Coastguard Worker G32( 8, InitDataSize);
318*f6dc9357SAndroid Build Coastguard Worker G32(12, UninitDataSize);
319*f6dc9357SAndroid Build Coastguard Worker // G32(16, AddressOfEntryPoint);
320*f6dc9357SAndroid Build Coastguard Worker // G32(20, BaseOfCode);
321*f6dc9357SAndroid Build Coastguard Worker
322*f6dc9357SAndroid Build Coastguard Worker G32(32, SectAlign);
323*f6dc9357SAndroid Build Coastguard Worker G32(36, FileAlign);
324*f6dc9357SAndroid Build Coastguard Worker
325*f6dc9357SAndroid Build Coastguard Worker OsVer.Parse(p + 40);
326*f6dc9357SAndroid Build Coastguard Worker ImageVer.Parse(p + 44);
327*f6dc9357SAndroid Build Coastguard Worker SubsysVer.Parse(p + 48);
328*f6dc9357SAndroid Build Coastguard Worker
329*f6dc9357SAndroid Build Coastguard Worker // reserved = Get32(p + 52);
330*f6dc9357SAndroid Build Coastguard Worker
331*f6dc9357SAndroid Build Coastguard Worker G32(56, ImageSize);
332*f6dc9357SAndroid Build Coastguard Worker G32(60, HeadersSize);
333*f6dc9357SAndroid Build Coastguard Worker G32(64, CheckSum);
334*f6dc9357SAndroid Build Coastguard Worker G16(68, SubSystem);
335*f6dc9357SAndroid Build Coastguard Worker G16(70, DllCharacts);
336*f6dc9357SAndroid Build Coastguard Worker
337*f6dc9357SAndroid Build Coastguard Worker UInt32 pos;
338*f6dc9357SAndroid Build Coastguard Worker if (Is64Bit())
339*f6dc9357SAndroid Build Coastguard Worker {
340*f6dc9357SAndroid Build Coastguard Worker if (size < k_OptHeader64_Size_MIN)
341*f6dc9357SAndroid Build Coastguard Worker return false;
342*f6dc9357SAndroid Build Coastguard Worker // BaseOfData32 = 0;
343*f6dc9357SAndroid Build Coastguard Worker G64(24, ImageBase);
344*f6dc9357SAndroid Build Coastguard Worker G64(72, StackReserve);
345*f6dc9357SAndroid Build Coastguard Worker G64(80, StackCommit);
346*f6dc9357SAndroid Build Coastguard Worker G64(88, HeapReserve);
347*f6dc9357SAndroid Build Coastguard Worker G64(96, HeapCommit);
348*f6dc9357SAndroid Build Coastguard Worker pos = 108;
349*f6dc9357SAndroid Build Coastguard Worker }
350*f6dc9357SAndroid Build Coastguard Worker else
351*f6dc9357SAndroid Build Coastguard Worker {
352*f6dc9357SAndroid Build Coastguard Worker // G32(24, BaseOfData32);
353*f6dc9357SAndroid Build Coastguard Worker G32(28, ImageBase);
354*f6dc9357SAndroid Build Coastguard Worker G32(72, StackReserve);
355*f6dc9357SAndroid Build Coastguard Worker G32(76, StackCommit);
356*f6dc9357SAndroid Build Coastguard Worker G32(80, HeapReserve);
357*f6dc9357SAndroid Build Coastguard Worker G32(84, HeapCommit);
358*f6dc9357SAndroid Build Coastguard Worker pos = 92;
359*f6dc9357SAndroid Build Coastguard Worker }
360*f6dc9357SAndroid Build Coastguard Worker
361*f6dc9357SAndroid Build Coastguard Worker UInt32 numDirItems;
362*f6dc9357SAndroid Build Coastguard Worker G32(pos, numDirItems);
363*f6dc9357SAndroid Build Coastguard Worker NumDirItems = numDirItems;
364*f6dc9357SAndroid Build Coastguard Worker if (numDirItems > (1 << 13))
365*f6dc9357SAndroid Build Coastguard Worker return false;
366*f6dc9357SAndroid Build Coastguard Worker pos += 4;
367*f6dc9357SAndroid Build Coastguard Worker if (pos + 8 * numDirItems > size)
368*f6dc9357SAndroid Build Coastguard Worker return false;
369*f6dc9357SAndroid Build Coastguard Worker memset((void *)DirItems, 0, sizeof(DirItems));
370*f6dc9357SAndroid Build Coastguard Worker if (numDirItems > kNumDirItemsMax)
371*f6dc9357SAndroid Build Coastguard Worker numDirItems = kNumDirItemsMax;
372*f6dc9357SAndroid Build Coastguard Worker for (UInt32 i = 0; i < numDirItems; i++)
373*f6dc9357SAndroid Build Coastguard Worker DirItems[i].Parse(p + pos + i * 8);
374*f6dc9357SAndroid Build Coastguard Worker return true;
375*f6dc9357SAndroid Build Coastguard Worker }
376*f6dc9357SAndroid Build Coastguard Worker
377*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kSectionSize = 40;
378*f6dc9357SAndroid Build Coastguard Worker
379*f6dc9357SAndroid Build Coastguard Worker struct CSection
380*f6dc9357SAndroid Build Coastguard Worker {
381*f6dc9357SAndroid Build Coastguard Worker AString Name;
382*f6dc9357SAndroid Build Coastguard Worker
383*f6dc9357SAndroid Build Coastguard Worker UInt32 ExtractSize;
384*f6dc9357SAndroid Build Coastguard Worker UInt32 VSize;
385*f6dc9357SAndroid Build Coastguard Worker UInt32 Va;
386*f6dc9357SAndroid Build Coastguard Worker UInt32 PSize;
387*f6dc9357SAndroid Build Coastguard Worker UInt32 Pa;
388*f6dc9357SAndroid Build Coastguard Worker UInt32 Flags;
389*f6dc9357SAndroid Build Coastguard Worker UInt32 Time;
390*f6dc9357SAndroid Build Coastguard Worker // UInt16 NumRelocs; // is set to zero for executable images
391*f6dc9357SAndroid Build Coastguard Worker bool IsRealSect;
392*f6dc9357SAndroid Build Coastguard Worker bool IsDebug;
393*f6dc9357SAndroid Build Coastguard Worker bool IsAdditionalSection;
394*f6dc9357SAndroid Build Coastguard Worker
CSectionNArchive::NPe::CSection395*f6dc9357SAndroid Build Coastguard Worker CSection():
396*f6dc9357SAndroid Build Coastguard Worker ExtractSize(0),
397*f6dc9357SAndroid Build Coastguard Worker IsRealSect(false),
398*f6dc9357SAndroid Build Coastguard Worker IsDebug(false),
399*f6dc9357SAndroid Build Coastguard Worker IsAdditionalSection(false)
400*f6dc9357SAndroid Build Coastguard Worker // , NumRelocs(0)
401*f6dc9357SAndroid Build Coastguard Worker {}
402*f6dc9357SAndroid Build Coastguard Worker
Set_Size_for_allNArchive::NPe::CSection403*f6dc9357SAndroid Build Coastguard Worker void Set_Size_for_all(UInt32 size)
404*f6dc9357SAndroid Build Coastguard Worker {
405*f6dc9357SAndroid Build Coastguard Worker PSize = VSize = ExtractSize = size;
406*f6dc9357SAndroid Build Coastguard Worker }
407*f6dc9357SAndroid Build Coastguard Worker
GetSize_ExtractNArchive::NPe::CSection408*f6dc9357SAndroid Build Coastguard Worker UInt32 GetSize_Extract() const
409*f6dc9357SAndroid Build Coastguard Worker {
410*f6dc9357SAndroid Build Coastguard Worker return ExtractSize;
411*f6dc9357SAndroid Build Coastguard Worker }
412*f6dc9357SAndroid Build Coastguard Worker
UpdateTotalSizeNArchive::NPe::CSection413*f6dc9357SAndroid Build Coastguard Worker void UpdateTotalSize(UInt32 &totalSize) const
414*f6dc9357SAndroid Build Coastguard Worker {
415*f6dc9357SAndroid Build Coastguard Worker const UInt32 t = Pa + PSize;
416*f6dc9357SAndroid Build Coastguard Worker if (totalSize < t)
417*f6dc9357SAndroid Build Coastguard Worker totalSize = t;
418*f6dc9357SAndroid Build Coastguard Worker }
419*f6dc9357SAndroid Build Coastguard Worker
420*f6dc9357SAndroid Build Coastguard Worker void Parse(const Byte *p);
421*f6dc9357SAndroid Build Coastguard Worker
CompareNArchive::NPe::CSection422*f6dc9357SAndroid Build Coastguard Worker int Compare(const CSection &s) const
423*f6dc9357SAndroid Build Coastguard Worker {
424*f6dc9357SAndroid Build Coastguard Worker RINOZ(MyCompare(Pa, s.Pa))
425*f6dc9357SAndroid Build Coastguard Worker const UInt32 size1 = GetSize_Extract();
426*f6dc9357SAndroid Build Coastguard Worker const UInt32 size2 = s.GetSize_Extract();
427*f6dc9357SAndroid Build Coastguard Worker return MyCompare(size1, size2);
428*f6dc9357SAndroid Build Coastguard Worker }
429*f6dc9357SAndroid Build Coastguard Worker };
430*f6dc9357SAndroid Build Coastguard Worker
431*f6dc9357SAndroid Build Coastguard Worker static const unsigned kNameSize = 8;
432*f6dc9357SAndroid Build Coastguard Worker
GetName(const Byte * name,AString & res)433*f6dc9357SAndroid Build Coastguard Worker static void GetName(const Byte *name, AString &res)
434*f6dc9357SAndroid Build Coastguard Worker {
435*f6dc9357SAndroid Build Coastguard Worker res.SetFrom_CalcLen((const char *)name, kNameSize);
436*f6dc9357SAndroid Build Coastguard Worker }
437*f6dc9357SAndroid Build Coastguard Worker
Parse(const Byte * p)438*f6dc9357SAndroid Build Coastguard Worker void CSection::Parse(const Byte *p)
439*f6dc9357SAndroid Build Coastguard Worker {
440*f6dc9357SAndroid Build Coastguard Worker GetName(p, Name);
441*f6dc9357SAndroid Build Coastguard Worker G32( 8, VSize);
442*f6dc9357SAndroid Build Coastguard Worker G32(12, Va);
443*f6dc9357SAndroid Build Coastguard Worker G32(16, PSize);
444*f6dc9357SAndroid Build Coastguard Worker G32(20, Pa);
445*f6dc9357SAndroid Build Coastguard Worker // G16(32, NumRelocs);
446*f6dc9357SAndroid Build Coastguard Worker G32(36, Flags);
447*f6dc9357SAndroid Build Coastguard Worker // v24.08: we extract only useful data (without extra padding bytes).
448*f6dc9357SAndroid Build Coastguard Worker // VSize == 0 is not expected, but we support that case too.
449*f6dc9357SAndroid Build Coastguard Worker // return (VSize && VSize < PSize) ? VSize : PSize;
450*f6dc9357SAndroid Build Coastguard Worker ExtractSize = (VSize && VSize < PSize) ? VSize : PSize;
451*f6dc9357SAndroid Build Coastguard Worker }
452*f6dc9357SAndroid Build Coastguard Worker
453*f6dc9357SAndroid Build Coastguard Worker
454*f6dc9357SAndroid Build Coastguard Worker
455*f6dc9357SAndroid Build Coastguard Worker // IMAGE_FILE_*
456*f6dc9357SAndroid Build Coastguard Worker
457*f6dc9357SAndroid Build Coastguard Worker static const CUInt32PCharPair g_HeaderCharacts[] =
458*f6dc9357SAndroid Build Coastguard Worker {
459*f6dc9357SAndroid Build Coastguard Worker { 1, "Executable" },
460*f6dc9357SAndroid Build Coastguard Worker { 13, "DLL" },
461*f6dc9357SAndroid Build Coastguard Worker { 8, "32-bit" },
462*f6dc9357SAndroid Build Coastguard Worker { 5, "LargeAddress" },
463*f6dc9357SAndroid Build Coastguard Worker { 0, "NoRelocs" },
464*f6dc9357SAndroid Build Coastguard Worker { 2, "NoLineNums" },
465*f6dc9357SAndroid Build Coastguard Worker { 3, "NoLocalSyms" },
466*f6dc9357SAndroid Build Coastguard Worker { 4, "AggressiveWsTrim" },
467*f6dc9357SAndroid Build Coastguard Worker { 9, "NoDebugInfo" },
468*f6dc9357SAndroid Build Coastguard Worker { 10, "RemovableRun" },
469*f6dc9357SAndroid Build Coastguard Worker { 11, "NetRun" },
470*f6dc9357SAndroid Build Coastguard Worker { 12, "System" },
471*f6dc9357SAndroid Build Coastguard Worker { 14, "UniCPU" },
472*f6dc9357SAndroid Build Coastguard Worker { 7, "Little-Endian" },
473*f6dc9357SAndroid Build Coastguard Worker { 15, "Big-Endian" }
474*f6dc9357SAndroid Build Coastguard Worker };
475*f6dc9357SAndroid Build Coastguard Worker
476*f6dc9357SAndroid Build Coastguard Worker // IMAGE_DLLCHARACTERISTICS_*
477*f6dc9357SAndroid Build Coastguard Worker
478*f6dc9357SAndroid Build Coastguard Worker static const char * const g_DllCharacts[] =
479*f6dc9357SAndroid Build Coastguard Worker {
480*f6dc9357SAndroid Build Coastguard Worker NULL
481*f6dc9357SAndroid Build Coastguard Worker , NULL
482*f6dc9357SAndroid Build Coastguard Worker , NULL
483*f6dc9357SAndroid Build Coastguard Worker , NULL
484*f6dc9357SAndroid Build Coastguard Worker , NULL
485*f6dc9357SAndroid Build Coastguard Worker , "HighEntropyVA"
486*f6dc9357SAndroid Build Coastguard Worker , "Relocated"
487*f6dc9357SAndroid Build Coastguard Worker , "Integrity"
488*f6dc9357SAndroid Build Coastguard Worker , "NX-Compatible"
489*f6dc9357SAndroid Build Coastguard Worker , "NoIsolation"
490*f6dc9357SAndroid Build Coastguard Worker , "NoSEH"
491*f6dc9357SAndroid Build Coastguard Worker , "NoBind"
492*f6dc9357SAndroid Build Coastguard Worker , "AppContainer"
493*f6dc9357SAndroid Build Coastguard Worker , "WDM"
494*f6dc9357SAndroid Build Coastguard Worker , "GuardCF"
495*f6dc9357SAndroid Build Coastguard Worker , "TerminalServerAware"
496*f6dc9357SAndroid Build Coastguard Worker };
497*f6dc9357SAndroid Build Coastguard Worker
498*f6dc9357SAndroid Build Coastguard Worker
499*f6dc9357SAndroid Build Coastguard Worker // IMAGE_SCN_* constants:
500*f6dc9357SAndroid Build Coastguard Worker
501*f6dc9357SAndroid Build Coastguard Worker static const char * const g_SectFlags[] =
502*f6dc9357SAndroid Build Coastguard Worker {
503*f6dc9357SAndroid Build Coastguard Worker NULL
504*f6dc9357SAndroid Build Coastguard Worker , NULL
505*f6dc9357SAndroid Build Coastguard Worker , NULL
506*f6dc9357SAndroid Build Coastguard Worker , "NoPad"
507*f6dc9357SAndroid Build Coastguard Worker , NULL
508*f6dc9357SAndroid Build Coastguard Worker , "Code"
509*f6dc9357SAndroid Build Coastguard Worker , "InitializedData"
510*f6dc9357SAndroid Build Coastguard Worker , "UninitializedData"
511*f6dc9357SAndroid Build Coastguard Worker , "Other"
512*f6dc9357SAndroid Build Coastguard Worker , "Comments"
513*f6dc9357SAndroid Build Coastguard Worker , NULL // OVER
514*f6dc9357SAndroid Build Coastguard Worker , "Remove"
515*f6dc9357SAndroid Build Coastguard Worker , "COMDAT"
516*f6dc9357SAndroid Build Coastguard Worker , NULL
517*f6dc9357SAndroid Build Coastguard Worker , "NO_DEFER_SPEC_EXC"
518*f6dc9357SAndroid Build Coastguard Worker , "GP" // MEM_FARDATA
519*f6dc9357SAndroid Build Coastguard Worker , NULL // SYSHEAP
520*f6dc9357SAndroid Build Coastguard Worker , "PURGEABLE" // 16BIT
521*f6dc9357SAndroid Build Coastguard Worker , "LOCKED"
522*f6dc9357SAndroid Build Coastguard Worker , "PRELOAD"
523*f6dc9357SAndroid Build Coastguard Worker , NULL
524*f6dc9357SAndroid Build Coastguard Worker , NULL
525*f6dc9357SAndroid Build Coastguard Worker , NULL
526*f6dc9357SAndroid Build Coastguard Worker , NULL
527*f6dc9357SAndroid Build Coastguard Worker , "ExtendedRelocations"
528*f6dc9357SAndroid Build Coastguard Worker , "Discardable"
529*f6dc9357SAndroid Build Coastguard Worker , "NotCached"
530*f6dc9357SAndroid Build Coastguard Worker , "NotPaged"
531*f6dc9357SAndroid Build Coastguard Worker , "Shared"
532*f6dc9357SAndroid Build Coastguard Worker , "Execute"
533*f6dc9357SAndroid Build Coastguard Worker , "Read"
534*f6dc9357SAndroid Build Coastguard Worker , "Write"
535*f6dc9357SAndroid Build Coastguard Worker };
536*f6dc9357SAndroid Build Coastguard Worker
537*f6dc9357SAndroid Build Coastguard Worker static const CUInt32PCharPair g_MachinePairs[] =
538*f6dc9357SAndroid Build Coastguard Worker {
539*f6dc9357SAndroid Build Coastguard Worker { 0x014C, "x86" },
540*f6dc9357SAndroid Build Coastguard Worker { 0x014D, "I860" },
541*f6dc9357SAndroid Build Coastguard Worker { 0x0162, "MIPS-R3000" },
542*f6dc9357SAndroid Build Coastguard Worker { 0x0166, "MIPS-R4000" },
543*f6dc9357SAndroid Build Coastguard Worker { 0x0168, "MIPS-R10000" },
544*f6dc9357SAndroid Build Coastguard Worker { 0x0169, "MIPS-V2" },
545*f6dc9357SAndroid Build Coastguard Worker { 0x0184, "Alpha" },
546*f6dc9357SAndroid Build Coastguard Worker { 0x01A2, "SH3" },
547*f6dc9357SAndroid Build Coastguard Worker { 0x01A3, "SH3-DSP" },
548*f6dc9357SAndroid Build Coastguard Worker { 0x01A4, "SH3E" },
549*f6dc9357SAndroid Build Coastguard Worker { 0x01A6, "SH4" },
550*f6dc9357SAndroid Build Coastguard Worker { 0x01A8, "SH5" },
551*f6dc9357SAndroid Build Coastguard Worker { 0x01C0, "ARM" },
552*f6dc9357SAndroid Build Coastguard Worker { 0x01C2, "ARM-Thumb" },
553*f6dc9357SAndroid Build Coastguard Worker { 0x01C4, "ARM-NT" },
554*f6dc9357SAndroid Build Coastguard Worker { 0x01D3, "AM33" },
555*f6dc9357SAndroid Build Coastguard Worker { 0x01F0, "PPC" },
556*f6dc9357SAndroid Build Coastguard Worker { 0x01F1, "PPC-FP" },
557*f6dc9357SAndroid Build Coastguard Worker { 0x01F2, "PPC-BE" },
558*f6dc9357SAndroid Build Coastguard Worker { 0x0200, "IA-64" },
559*f6dc9357SAndroid Build Coastguard Worker { 0x0266, "MIPS-16" },
560*f6dc9357SAndroid Build Coastguard Worker { 0x0284, "Alpha-64" },
561*f6dc9357SAndroid Build Coastguard Worker { 0x0366, "MIPS-FPU" },
562*f6dc9357SAndroid Build Coastguard Worker { 0x0466, "MIPS-FPU16" },
563*f6dc9357SAndroid Build Coastguard Worker { 0x0520, "TriCore" },
564*f6dc9357SAndroid Build Coastguard Worker { 0x0CEF, "CEF" },
565*f6dc9357SAndroid Build Coastguard Worker { 0x0EBC, "EFI" },
566*f6dc9357SAndroid Build Coastguard Worker { 0x5032, "RISCV32" },
567*f6dc9357SAndroid Build Coastguard Worker { 0x5064, "RISCV64" },
568*f6dc9357SAndroid Build Coastguard Worker // { 0x5128, "RISCV128" },
569*f6dc9357SAndroid Build Coastguard Worker { 0x6232, "LOONGARCH32" },
570*f6dc9357SAndroid Build Coastguard Worker { 0x6264, "LOONGARCH64" },
571*f6dc9357SAndroid Build Coastguard Worker { 0x8664, "x64" },
572*f6dc9357SAndroid Build Coastguard Worker { 0x9041, "M32R" },
573*f6dc9357SAndroid Build Coastguard Worker { 0xA641, "ARM64EC" },
574*f6dc9357SAndroid Build Coastguard Worker { 0xA64e, "ARM64X" },
575*f6dc9357SAndroid Build Coastguard Worker { 0xAA64, "ARM64" },
576*f6dc9357SAndroid Build Coastguard Worker { 0xC0EE, "CEE" }
577*f6dc9357SAndroid Build Coastguard Worker };
578*f6dc9357SAndroid Build Coastguard Worker
579*f6dc9357SAndroid Build Coastguard Worker static const char * const g_SubSystems[] =
580*f6dc9357SAndroid Build Coastguard Worker {
581*f6dc9357SAndroid Build Coastguard Worker "Unknown"
582*f6dc9357SAndroid Build Coastguard Worker , "Native"
583*f6dc9357SAndroid Build Coastguard Worker , "Windows GUI"
584*f6dc9357SAndroid Build Coastguard Worker , "Windows CUI"
585*f6dc9357SAndroid Build Coastguard Worker , NULL // "Old Windows CE"
586*f6dc9357SAndroid Build Coastguard Worker , "OS2"
587*f6dc9357SAndroid Build Coastguard Worker , NULL
588*f6dc9357SAndroid Build Coastguard Worker , "Posix"
589*f6dc9357SAndroid Build Coastguard Worker , "Win9x"
590*f6dc9357SAndroid Build Coastguard Worker , "Windows CE"
591*f6dc9357SAndroid Build Coastguard Worker , "EFI"
592*f6dc9357SAndroid Build Coastguard Worker , "EFI Boot"
593*f6dc9357SAndroid Build Coastguard Worker , "EFI Runtime"
594*f6dc9357SAndroid Build Coastguard Worker , "EFI ROM"
595*f6dc9357SAndroid Build Coastguard Worker , "XBOX"
596*f6dc9357SAndroid Build Coastguard Worker , NULL
597*f6dc9357SAndroid Build Coastguard Worker , "Windows Boot"
598*f6dc9357SAndroid Build Coastguard Worker , "XBOX Catalog" // 17
599*f6dc9357SAndroid Build Coastguard Worker };
600*f6dc9357SAndroid Build Coastguard Worker
601*f6dc9357SAndroid Build Coastguard Worker static const char * const g_ResTypes[] =
602*f6dc9357SAndroid Build Coastguard Worker {
603*f6dc9357SAndroid Build Coastguard Worker NULL
604*f6dc9357SAndroid Build Coastguard Worker , "CURSOR"
605*f6dc9357SAndroid Build Coastguard Worker , "BITMAP"
606*f6dc9357SAndroid Build Coastguard Worker , "ICON"
607*f6dc9357SAndroid Build Coastguard Worker , "MENU"
608*f6dc9357SAndroid Build Coastguard Worker , "DIALOG"
609*f6dc9357SAndroid Build Coastguard Worker , "STRING"
610*f6dc9357SAndroid Build Coastguard Worker , "FONTDIR"
611*f6dc9357SAndroid Build Coastguard Worker , "FONT"
612*f6dc9357SAndroid Build Coastguard Worker , "ACCELERATOR"
613*f6dc9357SAndroid Build Coastguard Worker , "RCDATA"
614*f6dc9357SAndroid Build Coastguard Worker , "MESSAGETABLE"
615*f6dc9357SAndroid Build Coastguard Worker , "GROUP_CURSOR"
616*f6dc9357SAndroid Build Coastguard Worker , NULL
617*f6dc9357SAndroid Build Coastguard Worker , "GROUP_ICON"
618*f6dc9357SAndroid Build Coastguard Worker , NULL
619*f6dc9357SAndroid Build Coastguard Worker , "VERSION"
620*f6dc9357SAndroid Build Coastguard Worker , "DLGINCLUDE"
621*f6dc9357SAndroid Build Coastguard Worker , NULL
622*f6dc9357SAndroid Build Coastguard Worker , "PLUGPLAY"
623*f6dc9357SAndroid Build Coastguard Worker , "VXD"
624*f6dc9357SAndroid Build Coastguard Worker , "ANICURSOR"
625*f6dc9357SAndroid Build Coastguard Worker , "ANIICON"
626*f6dc9357SAndroid Build Coastguard Worker , "HTML"
627*f6dc9357SAndroid Build Coastguard Worker , "MANIFEST"
628*f6dc9357SAndroid Build Coastguard Worker };
629*f6dc9357SAndroid Build Coastguard Worker
630*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kFlag = (UInt32)1 << 31;
631*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kMask = ~kFlag;
632*f6dc9357SAndroid Build Coastguard Worker
633*f6dc9357SAndroid Build Coastguard Worker struct CTableItem
634*f6dc9357SAndroid Build Coastguard Worker {
635*f6dc9357SAndroid Build Coastguard Worker UInt32 Offset;
636*f6dc9357SAndroid Build Coastguard Worker UInt32 ID;
637*f6dc9357SAndroid Build Coastguard Worker };
638*f6dc9357SAndroid Build Coastguard Worker
639*f6dc9357SAndroid Build Coastguard Worker
640*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kBmpHeaderSize = 14;
641*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kIconHeaderSize = 22;
642*f6dc9357SAndroid Build Coastguard Worker
643*f6dc9357SAndroid Build Coastguard Worker struct CResItem
644*f6dc9357SAndroid Build Coastguard Worker {
645*f6dc9357SAndroid Build Coastguard Worker UInt32 Type;
646*f6dc9357SAndroid Build Coastguard Worker UInt32 ID;
647*f6dc9357SAndroid Build Coastguard Worker UInt32 Lang;
648*f6dc9357SAndroid Build Coastguard Worker
649*f6dc9357SAndroid Build Coastguard Worker UInt32 Size;
650*f6dc9357SAndroid Build Coastguard Worker UInt32 Offset;
651*f6dc9357SAndroid Build Coastguard Worker
652*f6dc9357SAndroid Build Coastguard Worker UInt32 HeaderSize;
653*f6dc9357SAndroid Build Coastguard Worker Byte Header[kIconHeaderSize]; // it must be enough for max size header.
654*f6dc9357SAndroid Build Coastguard Worker bool Enabled;
655*f6dc9357SAndroid Build Coastguard Worker
IsNameEqualNArchive::NPe::CResItem656*f6dc9357SAndroid Build Coastguard Worker bool IsNameEqual(const CResItem &item) const { return Lang == item.Lang; }
GetSizeNArchive::NPe::CResItem657*f6dc9357SAndroid Build Coastguard Worker UInt32 GetSize() const { return Size + HeaderSize; }
IsBmpNArchive::NPe::CResItem658*f6dc9357SAndroid Build Coastguard Worker bool IsBmp() const { return Type == 2; }
IsIconNArchive::NPe::CResItem659*f6dc9357SAndroid Build Coastguard Worker bool IsIcon() const { return Type == 3; }
IsStringNArchive::NPe::CResItem660*f6dc9357SAndroid Build Coastguard Worker bool IsString() const { return Type == 6; }
IsRcDataNArchive::NPe::CResItem661*f6dc9357SAndroid Build Coastguard Worker bool IsRcData() const { return Type == 10; }
IsVersionNArchive::NPe::CResItem662*f6dc9357SAndroid Build Coastguard Worker bool IsVersion() const { return Type == 16; }
IsRcDataOrUnknownNArchive::NPe::CResItem663*f6dc9357SAndroid Build Coastguard Worker bool IsRcDataOrUnknown() const { return IsRcData() || Type > 64; }
664*f6dc9357SAndroid Build Coastguard Worker };
665*f6dc9357SAndroid Build Coastguard Worker
666*f6dc9357SAndroid Build Coastguard Worker struct CTextFile
667*f6dc9357SAndroid Build Coastguard Worker {
668*f6dc9357SAndroid Build Coastguard Worker CByteDynamicBuffer Buf;
669*f6dc9357SAndroid Build Coastguard Worker
FinalSizeNArchive::NPe::CTextFile670*f6dc9357SAndroid Build Coastguard Worker size_t FinalSize() const { return Buf.GetPos(); }
671*f6dc9357SAndroid Build Coastguard Worker
672*f6dc9357SAndroid Build Coastguard Worker void AddChar(char c);
673*f6dc9357SAndroid Build Coastguard Worker void AddWChar(UInt16 c);
674*f6dc9357SAndroid Build Coastguard Worker void AddWChar_Smart(UInt16 c);
675*f6dc9357SAndroid Build Coastguard Worker void NewLine();
676*f6dc9357SAndroid Build Coastguard Worker void AddString(const char *s);
677*f6dc9357SAndroid Build Coastguard Worker void AddSpaces(int num);
AddBytesNArchive::NPe::CTextFile678*f6dc9357SAndroid Build Coastguard Worker void AddBytes(const Byte *p, size_t size)
679*f6dc9357SAndroid Build Coastguard Worker {
680*f6dc9357SAndroid Build Coastguard Worker Buf.AddData(p, size);
681*f6dc9357SAndroid Build Coastguard Worker }
682*f6dc9357SAndroid Build Coastguard Worker
OpenBlockNArchive::NPe::CTextFile683*f6dc9357SAndroid Build Coastguard Worker void OpenBlock(int num)
684*f6dc9357SAndroid Build Coastguard Worker {
685*f6dc9357SAndroid Build Coastguard Worker AddSpaces(num);
686*f6dc9357SAndroid Build Coastguard Worker AddChar('{');
687*f6dc9357SAndroid Build Coastguard Worker NewLine();
688*f6dc9357SAndroid Build Coastguard Worker }
CloseBlockNArchive::NPe::CTextFile689*f6dc9357SAndroid Build Coastguard Worker void CloseBlock(int num)
690*f6dc9357SAndroid Build Coastguard Worker {
691*f6dc9357SAndroid Build Coastguard Worker AddSpaces(num);
692*f6dc9357SAndroid Build Coastguard Worker AddChar('}');
693*f6dc9357SAndroid Build Coastguard Worker NewLine();
694*f6dc9357SAndroid Build Coastguard Worker }
695*f6dc9357SAndroid Build Coastguard Worker };
696*f6dc9357SAndroid Build Coastguard Worker
AddChar(char c)697*f6dc9357SAndroid Build Coastguard Worker void CTextFile::AddChar(char c)
698*f6dc9357SAndroid Build Coastguard Worker {
699*f6dc9357SAndroid Build Coastguard Worker Byte *p = Buf.GetCurPtrAndGrow(2);
700*f6dc9357SAndroid Build Coastguard Worker p[0] = (Byte)c;
701*f6dc9357SAndroid Build Coastguard Worker p[1] = 0;
702*f6dc9357SAndroid Build Coastguard Worker }
703*f6dc9357SAndroid Build Coastguard Worker
AddWChar(UInt16 c)704*f6dc9357SAndroid Build Coastguard Worker void CTextFile::AddWChar(UInt16 c)
705*f6dc9357SAndroid Build Coastguard Worker {
706*f6dc9357SAndroid Build Coastguard Worker Byte *p = Buf.GetCurPtrAndGrow(2);
707*f6dc9357SAndroid Build Coastguard Worker SetUi16(p, c)
708*f6dc9357SAndroid Build Coastguard Worker }
709*f6dc9357SAndroid Build Coastguard Worker
AddWChar_Smart(UInt16 c)710*f6dc9357SAndroid Build Coastguard Worker void CTextFile::AddWChar_Smart(UInt16 c)
711*f6dc9357SAndroid Build Coastguard Worker {
712*f6dc9357SAndroid Build Coastguard Worker if (c == '\n')
713*f6dc9357SAndroid Build Coastguard Worker {
714*f6dc9357SAndroid Build Coastguard Worker AddChar('\\');
715*f6dc9357SAndroid Build Coastguard Worker c = 'n';
716*f6dc9357SAndroid Build Coastguard Worker }
717*f6dc9357SAndroid Build Coastguard Worker AddWChar(c);
718*f6dc9357SAndroid Build Coastguard Worker }
719*f6dc9357SAndroid Build Coastguard Worker
NewLine()720*f6dc9357SAndroid Build Coastguard Worker void CTextFile::NewLine()
721*f6dc9357SAndroid Build Coastguard Worker {
722*f6dc9357SAndroid Build Coastguard Worker AddChar(0x0D);
723*f6dc9357SAndroid Build Coastguard Worker AddChar(0x0A);
724*f6dc9357SAndroid Build Coastguard Worker }
725*f6dc9357SAndroid Build Coastguard Worker
AddString(const char * s)726*f6dc9357SAndroid Build Coastguard Worker void CTextFile::AddString(const char *s)
727*f6dc9357SAndroid Build Coastguard Worker {
728*f6dc9357SAndroid Build Coastguard Worker for (;; s++)
729*f6dc9357SAndroid Build Coastguard Worker {
730*f6dc9357SAndroid Build Coastguard Worker char c = *s;
731*f6dc9357SAndroid Build Coastguard Worker if (c == 0)
732*f6dc9357SAndroid Build Coastguard Worker return;
733*f6dc9357SAndroid Build Coastguard Worker AddChar(c);
734*f6dc9357SAndroid Build Coastguard Worker }
735*f6dc9357SAndroid Build Coastguard Worker }
736*f6dc9357SAndroid Build Coastguard Worker
AddSpaces(int num)737*f6dc9357SAndroid Build Coastguard Worker void CTextFile::AddSpaces(int num)
738*f6dc9357SAndroid Build Coastguard Worker {
739*f6dc9357SAndroid Build Coastguard Worker for (int i = 0; i < num; i++)
740*f6dc9357SAndroid Build Coastguard Worker AddChar(' ');
741*f6dc9357SAndroid Build Coastguard Worker }
742*f6dc9357SAndroid Build Coastguard Worker
743*f6dc9357SAndroid Build Coastguard Worker struct CStringItem: public CTextFile
744*f6dc9357SAndroid Build Coastguard Worker {
745*f6dc9357SAndroid Build Coastguard Worker UInt32 Lang;
746*f6dc9357SAndroid Build Coastguard Worker };
747*f6dc9357SAndroid Build Coastguard Worker
748*f6dc9357SAndroid Build Coastguard Worker struct CByteBuffer_WithLang: public CByteBuffer
749*f6dc9357SAndroid Build Coastguard Worker {
750*f6dc9357SAndroid Build Coastguard Worker UInt32 Lang;
751*f6dc9357SAndroid Build Coastguard Worker };
752*f6dc9357SAndroid Build Coastguard Worker
753*f6dc9357SAndroid Build Coastguard Worker
754*f6dc9357SAndroid Build Coastguard Worker struct CMixItem
755*f6dc9357SAndroid Build Coastguard Worker {
756*f6dc9357SAndroid Build Coastguard Worker int SectionIndex;
757*f6dc9357SAndroid Build Coastguard Worker int ResourceIndex;
758*f6dc9357SAndroid Build Coastguard Worker int StringIndex;
759*f6dc9357SAndroid Build Coastguard Worker int VersionIndex;
760*f6dc9357SAndroid Build Coastguard Worker
CMixItemNArchive::NPe::CMixItem761*f6dc9357SAndroid Build Coastguard Worker CMixItem(): SectionIndex(-1), ResourceIndex(-1), StringIndex(-1), VersionIndex(-1) {}
IsSectionItemNArchive::NPe::CMixItem762*f6dc9357SAndroid Build Coastguard Worker bool IsSectionItem() const { return ResourceIndex < 0 && StringIndex < 0 && VersionIndex < 0; }
763*f6dc9357SAndroid Build Coastguard Worker };
764*f6dc9357SAndroid Build Coastguard Worker
765*f6dc9357SAndroid Build Coastguard Worker struct CUsedBitmap
766*f6dc9357SAndroid Build Coastguard Worker {
767*f6dc9357SAndroid Build Coastguard Worker CByteBuffer Buf;
768*f6dc9357SAndroid Build Coastguard Worker public:
AllocNArchive::NPe::CUsedBitmap769*f6dc9357SAndroid Build Coastguard Worker void Alloc(size_t size)
770*f6dc9357SAndroid Build Coastguard Worker {
771*f6dc9357SAndroid Build Coastguard Worker size = (size + 7) / 8;
772*f6dc9357SAndroid Build Coastguard Worker Buf.Alloc(size);
773*f6dc9357SAndroid Build Coastguard Worker memset(Buf, 0, size);
774*f6dc9357SAndroid Build Coastguard Worker }
775*f6dc9357SAndroid Build Coastguard Worker
FreeNArchive::NPe::CUsedBitmap776*f6dc9357SAndroid Build Coastguard Worker void Free()
777*f6dc9357SAndroid Build Coastguard Worker {
778*f6dc9357SAndroid Build Coastguard Worker Buf.Free();
779*f6dc9357SAndroid Build Coastguard Worker }
780*f6dc9357SAndroid Build Coastguard Worker
SetRangeNArchive::NPe::CUsedBitmap781*f6dc9357SAndroid Build Coastguard Worker bool SetRange(size_t from, unsigned size)
782*f6dc9357SAndroid Build Coastguard Worker {
783*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < size; i++)
784*f6dc9357SAndroid Build Coastguard Worker {
785*f6dc9357SAndroid Build Coastguard Worker size_t pos = (from + i) >> 3;
786*f6dc9357SAndroid Build Coastguard Worker Byte mask = (Byte)(1 << ((from + i) & 7));
787*f6dc9357SAndroid Build Coastguard Worker Byte b = Buf[pos];
788*f6dc9357SAndroid Build Coastguard Worker if ((b & mask) != 0)
789*f6dc9357SAndroid Build Coastguard Worker return false;
790*f6dc9357SAndroid Build Coastguard Worker Buf[pos] = (Byte)(b | mask);
791*f6dc9357SAndroid Build Coastguard Worker }
792*f6dc9357SAndroid Build Coastguard Worker return true;
793*f6dc9357SAndroid Build Coastguard Worker }
794*f6dc9357SAndroid Build Coastguard Worker };
795*f6dc9357SAndroid Build Coastguard Worker
796*f6dc9357SAndroid Build Coastguard Worker struct CStringKeyValue
797*f6dc9357SAndroid Build Coastguard Worker {
798*f6dc9357SAndroid Build Coastguard Worker UString Key;
799*f6dc9357SAndroid Build Coastguard Worker UString Value;
800*f6dc9357SAndroid Build Coastguard Worker };
801*f6dc9357SAndroid Build Coastguard Worker
802*f6dc9357SAndroid Build Coastguard Worker
803*f6dc9357SAndroid Build Coastguard Worker Z7_CLASS_IMP_CHandler_IInArchive_2(
804*f6dc9357SAndroid Build Coastguard Worker IInArchiveGetStream,
805*f6dc9357SAndroid Build Coastguard Worker IArchiveAllowTail
806*f6dc9357SAndroid Build Coastguard Worker )
807*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IInStream> _stream;
808*f6dc9357SAndroid Build Coastguard Worker CObjectVector<CSection> _sections;
809*f6dc9357SAndroid Build Coastguard Worker CHeader _header;
810*f6dc9357SAndroid Build Coastguard Worker UInt32 _totalSize;
811*f6dc9357SAndroid Build Coastguard Worker Int32 _mainSubfile;
812*f6dc9357SAndroid Build Coastguard Worker
813*f6dc9357SAndroid Build Coastguard Worker CRecordVector<CMixItem> _mixItems;
814*f6dc9357SAndroid Build Coastguard Worker CRecordVector<CResItem> _items;
815*f6dc9357SAndroid Build Coastguard Worker CObjectVector<CStringItem> _strings;
816*f6dc9357SAndroid Build Coastguard Worker CObjectVector<CByteBuffer_WithLang> _versionFiles;
817*f6dc9357SAndroid Build Coastguard Worker UString _versionFullString;
818*f6dc9357SAndroid Build Coastguard Worker UString _versionShortString;
819*f6dc9357SAndroid Build Coastguard Worker UString _originalFilename;
820*f6dc9357SAndroid Build Coastguard Worker CObjectVector<CStringKeyValue> _versionKeys;
821*f6dc9357SAndroid Build Coastguard Worker
822*f6dc9357SAndroid Build Coastguard Worker CByteBuffer _buf;
823*f6dc9357SAndroid Build Coastguard Worker bool _oneLang;
824*f6dc9357SAndroid Build Coastguard Worker UString _resourcesPrefix;
825*f6dc9357SAndroid Build Coastguard Worker CUsedBitmap _usedRes;
826*f6dc9357SAndroid Build Coastguard Worker // bool _parseResources;
827*f6dc9357SAndroid Build Coastguard Worker bool _checksumError;
828*f6dc9357SAndroid Build Coastguard Worker bool _sectionsError;
829*f6dc9357SAndroid Build Coastguard Worker
IsOpt() const830*f6dc9357SAndroid Build Coastguard Worker bool IsOpt() const { return _header.OptHeaderSize != 0; }
831*f6dc9357SAndroid Build Coastguard Worker
832*f6dc9357SAndroid Build Coastguard Worker COptHeader _optHeader;
833*f6dc9357SAndroid Build Coastguard Worker
834*f6dc9357SAndroid Build Coastguard Worker bool _coffMode;
835*f6dc9357SAndroid Build Coastguard Worker bool _allowTail;
836*f6dc9357SAndroid Build Coastguard Worker
837*f6dc9357SAndroid Build Coastguard Worker HRESULT LoadDebugSections(IInStream *stream, bool &thereIsSection);
838*f6dc9357SAndroid Build Coastguard Worker HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback);
839*f6dc9357SAndroid Build Coastguard Worker
840*f6dc9357SAndroid Build Coastguard Worker void AddResNameToString(UString &s, UInt32 id) const;
841*f6dc9357SAndroid Build Coastguard Worker void AddLangPrefix(UString &s, UInt32 lang) const;
842*f6dc9357SAndroid Build Coastguard Worker HRESULT ReadString(UInt32 offset, UString &dest) const;
843*f6dc9357SAndroid Build Coastguard Worker HRESULT ReadTable(UInt32 offset, CRecordVector<CTableItem> &items);
844*f6dc9357SAndroid Build Coastguard Worker bool ParseStringRes(UInt32 id, UInt32 lang, const Byte *src, UInt32 size);
845*f6dc9357SAndroid Build Coastguard Worker HRESULT OpenResources(unsigned sectIndex, IInStream *stream, IArchiveOpenCallback *callback);
846*f6dc9357SAndroid Build Coastguard Worker void CloseResources();
847*f6dc9357SAndroid Build Coastguard Worker
848*f6dc9357SAndroid Build Coastguard Worker
CheckItem(const CSection & sect,const CResItem & item,size_t offset) const849*f6dc9357SAndroid Build Coastguard Worker bool CheckItem(const CSection §, const CResItem &item, size_t offset) const
850*f6dc9357SAndroid Build Coastguard Worker {
851*f6dc9357SAndroid Build Coastguard Worker return item.Offset >= sect.Va && offset <= _buf.Size() && _buf.Size() - offset >= item.Size;
852*f6dc9357SAndroid Build Coastguard Worker }
853*f6dc9357SAndroid Build Coastguard Worker
854*f6dc9357SAndroid Build Coastguard Worker public:
855*f6dc9357SAndroid Build Coastguard Worker CHandler(bool coffMode = false):
856*f6dc9357SAndroid Build Coastguard Worker _coffMode(coffMode),
857*f6dc9357SAndroid Build Coastguard Worker _allowTail(coffMode)
858*f6dc9357SAndroid Build Coastguard Worker {}
859*f6dc9357SAndroid Build Coastguard Worker };
860*f6dc9357SAndroid Build Coastguard Worker
861*f6dc9357SAndroid Build Coastguard Worker
862*f6dc9357SAndroid Build Coastguard Worker enum
863*f6dc9357SAndroid Build Coastguard Worker {
864*f6dc9357SAndroid Build Coastguard Worker kpidSectAlign = kpidUserDefined,
865*f6dc9357SAndroid Build Coastguard Worker kpidFileAlign,
866*f6dc9357SAndroid Build Coastguard Worker kpidLinkerVer,
867*f6dc9357SAndroid Build Coastguard Worker kpidOsVer,
868*f6dc9357SAndroid Build Coastguard Worker kpidImageVer,
869*f6dc9357SAndroid Build Coastguard Worker kpidSubsysVer,
870*f6dc9357SAndroid Build Coastguard Worker kpidCodeSize,
871*f6dc9357SAndroid Build Coastguard Worker kpidImageSize,
872*f6dc9357SAndroid Build Coastguard Worker kpidInitDataSize,
873*f6dc9357SAndroid Build Coastguard Worker kpidUnInitDataSize,
874*f6dc9357SAndroid Build Coastguard Worker kpidHeadersSizeUnInitDataSize,
875*f6dc9357SAndroid Build Coastguard Worker kpidSubSystem,
876*f6dc9357SAndroid Build Coastguard Worker kpidDllCharacts,
877*f6dc9357SAndroid Build Coastguard Worker kpidStackReserve,
878*f6dc9357SAndroid Build Coastguard Worker kpidStackCommit,
879*f6dc9357SAndroid Build Coastguard Worker kpidHeapReserve,
880*f6dc9357SAndroid Build Coastguard Worker kpidHeapCommit
881*f6dc9357SAndroid Build Coastguard Worker // , kpidImageBase
882*f6dc9357SAndroid Build Coastguard Worker // , kpidAddressOfEntryPoint
883*f6dc9357SAndroid Build Coastguard Worker // , kpidBaseOfCode
884*f6dc9357SAndroid Build Coastguard Worker // , kpidBaseOfData32
885*f6dc9357SAndroid Build Coastguard Worker };
886*f6dc9357SAndroid Build Coastguard Worker
887*f6dc9357SAndroid Build Coastguard Worker static const CStatProp kArcProps[] =
888*f6dc9357SAndroid Build Coastguard Worker {
889*f6dc9357SAndroid Build Coastguard Worker // { NULL, kpidWarning, VT_BSTR},
890*f6dc9357SAndroid Build Coastguard Worker { NULL, kpidCpu, VT_BSTR},
891*f6dc9357SAndroid Build Coastguard Worker { NULL, kpidBit64, VT_BOOL},
892*f6dc9357SAndroid Build Coastguard Worker { NULL, kpidCharacts, VT_BSTR},
893*f6dc9357SAndroid Build Coastguard Worker { NULL, kpidCTime, VT_FILETIME},
894*f6dc9357SAndroid Build Coastguard Worker { NULL, kpidHeadersSize, VT_UI4},
895*f6dc9357SAndroid Build Coastguard Worker { NULL, kpidChecksum, VT_UI4},
896*f6dc9357SAndroid Build Coastguard Worker { NULL, kpidName, VT_BSTR},
897*f6dc9357SAndroid Build Coastguard Worker
898*f6dc9357SAndroid Build Coastguard Worker { "Image Size", kpidImageSize, VT_UI4},
899*f6dc9357SAndroid Build Coastguard Worker { "Section Alignment", kpidSectAlign, VT_UI4},
900*f6dc9357SAndroid Build Coastguard Worker { "File Alignment", kpidFileAlign, VT_UI4},
901*f6dc9357SAndroid Build Coastguard Worker { "Code Size", kpidCodeSize, VT_UI4},
902*f6dc9357SAndroid Build Coastguard Worker { "Initialized Data Size", kpidInitDataSize, VT_UI4},
903*f6dc9357SAndroid Build Coastguard Worker { "Uninitialized Data Size", kpidUnInitDataSize, VT_UI4},
904*f6dc9357SAndroid Build Coastguard Worker { "Linker Version", kpidLinkerVer, VT_BSTR},
905*f6dc9357SAndroid Build Coastguard Worker { "OS Version", kpidOsVer, VT_BSTR},
906*f6dc9357SAndroid Build Coastguard Worker { "Image Version", kpidImageVer, VT_BSTR},
907*f6dc9357SAndroid Build Coastguard Worker { "Subsystem Version", kpidSubsysVer, VT_BSTR},
908*f6dc9357SAndroid Build Coastguard Worker { "Subsystem", kpidSubSystem, VT_BSTR},
909*f6dc9357SAndroid Build Coastguard Worker { "DLL Characteristics", kpidDllCharacts, VT_BSTR},
910*f6dc9357SAndroid Build Coastguard Worker { "Stack Reserve", kpidStackReserve, VT_UI8},
911*f6dc9357SAndroid Build Coastguard Worker { "Stack Commit", kpidStackCommit, VT_UI8},
912*f6dc9357SAndroid Build Coastguard Worker { "Heap Reserve", kpidHeapReserve, VT_UI8},
913*f6dc9357SAndroid Build Coastguard Worker { "Heap Commit", kpidHeapCommit, VT_UI8},
914*f6dc9357SAndroid Build Coastguard Worker { NULL, kpidVa, VT_UI8 }, // "Image Base", kpidImageBase, VT_UI8
915*f6dc9357SAndroid Build Coastguard Worker { NULL, kpidComment, VT_BSTR}
916*f6dc9357SAndroid Build Coastguard Worker
917*f6dc9357SAndroid Build Coastguard Worker // , { "Address Of Entry Point", kpidAddressOfEntryPoint, VT_UI8}
918*f6dc9357SAndroid Build Coastguard Worker // , { "Base Of Code", kpidBaseOfCode, VT_UI8}
919*f6dc9357SAndroid Build Coastguard Worker // , { "Base Of Data", kpidBaseOfData32, VT_UI8}
920*f6dc9357SAndroid Build Coastguard Worker };
921*f6dc9357SAndroid Build Coastguard Worker
922*f6dc9357SAndroid Build Coastguard Worker // #define kpid_NumRelocs 250
923*f6dc9357SAndroid Build Coastguard Worker
924*f6dc9357SAndroid Build Coastguard Worker static const Byte kProps[] =
925*f6dc9357SAndroid Build Coastguard Worker {
926*f6dc9357SAndroid Build Coastguard Worker kpidPath,
927*f6dc9357SAndroid Build Coastguard Worker kpidSize,
928*f6dc9357SAndroid Build Coastguard Worker kpidPackSize,
929*f6dc9357SAndroid Build Coastguard Worker kpidVirtualSize,
930*f6dc9357SAndroid Build Coastguard Worker kpidCharacts,
931*f6dc9357SAndroid Build Coastguard Worker kpidOffset,
932*f6dc9357SAndroid Build Coastguard Worker kpidVa
933*f6dc9357SAndroid Build Coastguard Worker // , kpid_NumRelocs
934*f6dc9357SAndroid Build Coastguard Worker };
935*f6dc9357SAndroid Build Coastguard Worker
936*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_Props
937*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_ArcProps_WITH_NAME
938*f6dc9357SAndroid Build Coastguard Worker
939*f6dc9357SAndroid Build Coastguard Worker static void TimeToProp(UInt32 unixTime, NCOM::CPropVariant &prop)
940*f6dc9357SAndroid Build Coastguard Worker {
941*f6dc9357SAndroid Build Coastguard Worker if (unixTime != 0)
942*f6dc9357SAndroid Build Coastguard Worker PropVariant_SetFrom_UnixTime(prop, unixTime);
943*f6dc9357SAndroid Build Coastguard Worker }
944*f6dc9357SAndroid Build Coastguard Worker
945*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
946*f6dc9357SAndroid Build Coastguard Worker {
947*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
948*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop;
949*f6dc9357SAndroid Build Coastguard Worker switch (propID)
950*f6dc9357SAndroid Build Coastguard Worker {
951*f6dc9357SAndroid Build Coastguard Worker case kpidPhySize: prop = _totalSize; break;
952*f6dc9357SAndroid Build Coastguard Worker case kpidComment:
953*f6dc9357SAndroid Build Coastguard Worker {
954*f6dc9357SAndroid Build Coastguard Worker UString s (_versionFullString);
955*f6dc9357SAndroid Build Coastguard Worker s.Add_LF();
956*f6dc9357SAndroid Build Coastguard Worker s += "Data Directories: ";
957*f6dc9357SAndroid Build Coastguard Worker s.Add_UInt32(_optHeader.NumDirItems);
958*f6dc9357SAndroid Build Coastguard Worker s.Add_LF();
959*f6dc9357SAndroid Build Coastguard Worker s.Add_Char('{');
960*f6dc9357SAndroid Build Coastguard Worker s.Add_LF();
961*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < _optHeader.NumDirItems
962*f6dc9357SAndroid Build Coastguard Worker && i < Z7_ARRAY_SIZE(_optHeader.DirItems); i++)
963*f6dc9357SAndroid Build Coastguard Worker {
964*f6dc9357SAndroid Build Coastguard Worker const CDirLink &di = _optHeader.DirItems[i];
965*f6dc9357SAndroid Build Coastguard Worker if (di.Va == 0 && di.Size == 0)
966*f6dc9357SAndroid Build Coastguard Worker continue;
967*f6dc9357SAndroid Build Coastguard Worker s += "index=";
968*f6dc9357SAndroid Build Coastguard Worker s.Add_UInt32(i);
969*f6dc9357SAndroid Build Coastguard Worker
970*f6dc9357SAndroid Build Coastguard Worker if (i < Z7_ARRAY_SIZE(g_Dir_Names))
971*f6dc9357SAndroid Build Coastguard Worker {
972*f6dc9357SAndroid Build Coastguard Worker s += " name=";
973*f6dc9357SAndroid Build Coastguard Worker s += g_Dir_Names[i];
974*f6dc9357SAndroid Build Coastguard Worker }
975*f6dc9357SAndroid Build Coastguard Worker s += " VA=0x";
976*f6dc9357SAndroid Build Coastguard Worker char temp[16];
977*f6dc9357SAndroid Build Coastguard Worker ConvertUInt32ToHex(di.Va, temp);
978*f6dc9357SAndroid Build Coastguard Worker s += temp;
979*f6dc9357SAndroid Build Coastguard Worker s += " Size=";
980*f6dc9357SAndroid Build Coastguard Worker s.Add_UInt32(di.Size);
981*f6dc9357SAndroid Build Coastguard Worker s.Add_LF();
982*f6dc9357SAndroid Build Coastguard Worker }
983*f6dc9357SAndroid Build Coastguard Worker s.Add_Char('}');
984*f6dc9357SAndroid Build Coastguard Worker s.Add_LF();
985*f6dc9357SAndroid Build Coastguard Worker prop = s;
986*f6dc9357SAndroid Build Coastguard Worker break;
987*f6dc9357SAndroid Build Coastguard Worker }
988*f6dc9357SAndroid Build Coastguard Worker case kpidShortComment:
989*f6dc9357SAndroid Build Coastguard Worker if (!_versionShortString.IsEmpty())
990*f6dc9357SAndroid Build Coastguard Worker prop = _versionShortString;
991*f6dc9357SAndroid Build Coastguard Worker else
992*f6dc9357SAndroid Build Coastguard Worker {
993*f6dc9357SAndroid Build Coastguard Worker PAIR_TO_PROP(g_MachinePairs, _header.Machine, prop);
994*f6dc9357SAndroid Build Coastguard Worker }
995*f6dc9357SAndroid Build Coastguard Worker break;
996*f6dc9357SAndroid Build Coastguard Worker
997*f6dc9357SAndroid Build Coastguard Worker case kpidName: if (!_originalFilename.IsEmpty()) prop = _originalFilename; break;
998*f6dc9357SAndroid Build Coastguard Worker
999*f6dc9357SAndroid Build Coastguard Worker // case kpidIsSelfExe: prop = !_header.IsDll(); break;
1000*f6dc9357SAndroid Build Coastguard Worker // case kpidError:
1001*f6dc9357SAndroid Build Coastguard Worker case kpidWarning: if (_checksumError) prop = "Checksum error"; break;
1002*f6dc9357SAndroid Build Coastguard Worker
1003*f6dc9357SAndroid Build Coastguard Worker case kpidWarningFlags:
1004*f6dc9357SAndroid Build Coastguard Worker {
1005*f6dc9357SAndroid Build Coastguard Worker UInt32 v = 0;
1006*f6dc9357SAndroid Build Coastguard Worker if (_sectionsError) v |= kpv_ErrorFlags_HeadersError;
1007*f6dc9357SAndroid Build Coastguard Worker if (v != 0)
1008*f6dc9357SAndroid Build Coastguard Worker prop = v;
1009*f6dc9357SAndroid Build Coastguard Worker break;
1010*f6dc9357SAndroid Build Coastguard Worker }
1011*f6dc9357SAndroid Build Coastguard Worker
1012*f6dc9357SAndroid Build Coastguard Worker case kpidCpu: PAIR_TO_PROP(g_MachinePairs, _header.Machine, prop); break;
1013*f6dc9357SAndroid Build Coastguard Worker case kpidMTime:
1014*f6dc9357SAndroid Build Coastguard Worker case kpidCTime: TimeToProp(_header.Time, prop); break;
1015*f6dc9357SAndroid Build Coastguard Worker case kpidCharacts: FLAGS_TO_PROP(g_HeaderCharacts, _header.Flags, prop); break;
1016*f6dc9357SAndroid Build Coastguard Worker case kpidMainSubfile: if (_mainSubfile >= 0) prop = (UInt32)_mainSubfile; break;
1017*f6dc9357SAndroid Build Coastguard Worker
1018*f6dc9357SAndroid Build Coastguard Worker default:
1019*f6dc9357SAndroid Build Coastguard Worker if (IsOpt())
1020*f6dc9357SAndroid Build Coastguard Worker switch (propID)
1021*f6dc9357SAndroid Build Coastguard Worker {
1022*f6dc9357SAndroid Build Coastguard Worker
1023*f6dc9357SAndroid Build Coastguard Worker case kpidSectAlign: prop = _optHeader.SectAlign; break;
1024*f6dc9357SAndroid Build Coastguard Worker case kpidFileAlign: prop = _optHeader.FileAlign; break;
1025*f6dc9357SAndroid Build Coastguard Worker case kpidLinkerVer:
1026*f6dc9357SAndroid Build Coastguard Worker {
1027*f6dc9357SAndroid Build Coastguard Worker CVersion v = { _optHeader.LinkerVerMajor, _optHeader.LinkerVerMinor };
1028*f6dc9357SAndroid Build Coastguard Worker v.ToProp(prop);
1029*f6dc9357SAndroid Build Coastguard Worker break;
1030*f6dc9357SAndroid Build Coastguard Worker }
1031*f6dc9357SAndroid Build Coastguard Worker
1032*f6dc9357SAndroid Build Coastguard Worker case kpidOsVer: _optHeader.OsVer.ToProp(prop); break;
1033*f6dc9357SAndroid Build Coastguard Worker case kpidImageVer: _optHeader.ImageVer.ToProp(prop); break;
1034*f6dc9357SAndroid Build Coastguard Worker case kpidSubsysVer: _optHeader.SubsysVer.ToProp(prop); break;
1035*f6dc9357SAndroid Build Coastguard Worker case kpidCodeSize: prop = _optHeader.CodeSize; break;
1036*f6dc9357SAndroid Build Coastguard Worker case kpidInitDataSize: prop = _optHeader.InitDataSize; break;
1037*f6dc9357SAndroid Build Coastguard Worker case kpidUnInitDataSize: prop = _optHeader.UninitDataSize; break;
1038*f6dc9357SAndroid Build Coastguard Worker case kpidImageSize: prop = _optHeader.ImageSize; break;
1039*f6dc9357SAndroid Build Coastguard Worker case kpidHeadersSize: prop = _optHeader.HeadersSize; break;
1040*f6dc9357SAndroid Build Coastguard Worker case kpidChecksum: prop = _optHeader.CheckSum; break;
1041*f6dc9357SAndroid Build Coastguard Worker
1042*f6dc9357SAndroid Build Coastguard Worker case kpidExtension:
1043*f6dc9357SAndroid Build Coastguard Worker if (_header.IsDll())
1044*f6dc9357SAndroid Build Coastguard Worker prop = "dll";
1045*f6dc9357SAndroid Build Coastguard Worker else if (_optHeader.IsSybSystem_EFI())
1046*f6dc9357SAndroid Build Coastguard Worker prop = "efi";
1047*f6dc9357SAndroid Build Coastguard Worker break;
1048*f6dc9357SAndroid Build Coastguard Worker
1049*f6dc9357SAndroid Build Coastguard Worker case kpidBit64: if (_optHeader.Is64Bit()) prop = true; break;
1050*f6dc9357SAndroid Build Coastguard Worker case kpidSubSystem: TYPE_TO_PROP(g_SubSystems, _optHeader.SubSystem, prop); break;
1051*f6dc9357SAndroid Build Coastguard Worker
1052*f6dc9357SAndroid Build Coastguard Worker case kpidDllCharacts: FLAGS_TO_PROP(g_DllCharacts, _optHeader.DllCharacts, prop); break;
1053*f6dc9357SAndroid Build Coastguard Worker case kpidStackReserve: prop = _optHeader.StackReserve; break;
1054*f6dc9357SAndroid Build Coastguard Worker case kpidStackCommit: prop = _optHeader.StackCommit; break;
1055*f6dc9357SAndroid Build Coastguard Worker case kpidHeapReserve: prop = _optHeader.HeapReserve; break;
1056*f6dc9357SAndroid Build Coastguard Worker case kpidHeapCommit: prop = _optHeader.HeapCommit; break;
1057*f6dc9357SAndroid Build Coastguard Worker case kpidVa: prop = _optHeader.ImageBase; break; // kpidImageBase:
1058*f6dc9357SAndroid Build Coastguard Worker // case kpidAddressOfEntryPoint: prop = _optHeader.AddressOfEntryPoint; break;
1059*f6dc9357SAndroid Build Coastguard Worker // case kpidBaseOfCode: prop = _optHeader.BaseOfCode; break;
1060*f6dc9357SAndroid Build Coastguard Worker // case kpidBaseOfData32: if (!_optHeader.Is64Bit()) prop = _optHeader.BaseOfData32; break;
1061*f6dc9357SAndroid Build Coastguard Worker }
1062*f6dc9357SAndroid Build Coastguard Worker }
1063*f6dc9357SAndroid Build Coastguard Worker prop.Detach(value);
1064*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1065*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
1066*f6dc9357SAndroid Build Coastguard Worker }
1067*f6dc9357SAndroid Build Coastguard Worker
1068*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::ReadString(UInt32 offset, UString &dest) const
1069*f6dc9357SAndroid Build Coastguard Worker {
1070*f6dc9357SAndroid Build Coastguard Worker if ((offset & 1) != 0 || offset >= _buf.Size())
1071*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1072*f6dc9357SAndroid Build Coastguard Worker size_t rem = _buf.Size() - offset;
1073*f6dc9357SAndroid Build Coastguard Worker if (rem < 2)
1074*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1075*f6dc9357SAndroid Build Coastguard Worker unsigned len = Get16(_buf + offset);
1076*f6dc9357SAndroid Build Coastguard Worker if ((rem - 2) / 2 < len)
1077*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1078*f6dc9357SAndroid Build Coastguard Worker dest.Empty();
1079*f6dc9357SAndroid Build Coastguard Worker wchar_t *destBuf = dest.GetBuf(len);
1080*f6dc9357SAndroid Build Coastguard Worker offset += 2;
1081*f6dc9357SAndroid Build Coastguard Worker const Byte *src = _buf + offset;
1082*f6dc9357SAndroid Build Coastguard Worker unsigned i;
1083*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < len; i++)
1084*f6dc9357SAndroid Build Coastguard Worker {
1085*f6dc9357SAndroid Build Coastguard Worker wchar_t c = (wchar_t)Get16(src + i * 2);
1086*f6dc9357SAndroid Build Coastguard Worker if (c == 0)
1087*f6dc9357SAndroid Build Coastguard Worker break;
1088*f6dc9357SAndroid Build Coastguard Worker destBuf[i] = c;
1089*f6dc9357SAndroid Build Coastguard Worker }
1090*f6dc9357SAndroid Build Coastguard Worker destBuf[i] = 0;
1091*f6dc9357SAndroid Build Coastguard Worker dest.ReleaseBuf_SetLen(i);
1092*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1093*f6dc9357SAndroid Build Coastguard Worker }
1094*f6dc9357SAndroid Build Coastguard Worker
1095*f6dc9357SAndroid Build Coastguard Worker void CHandler::AddResNameToString(UString &s, UInt32 id) const
1096*f6dc9357SAndroid Build Coastguard Worker {
1097*f6dc9357SAndroid Build Coastguard Worker if ((id & kFlag) != 0)
1098*f6dc9357SAndroid Build Coastguard Worker {
1099*f6dc9357SAndroid Build Coastguard Worker UString name;
1100*f6dc9357SAndroid Build Coastguard Worker if (ReadString(id & kMask, name) == S_OK)
1101*f6dc9357SAndroid Build Coastguard Worker {
1102*f6dc9357SAndroid Build Coastguard Worker const wchar_t *str = L"[]";
1103*f6dc9357SAndroid Build Coastguard Worker if (name.Len() > 1 && name[0] == '"' && name.Back() == '"')
1104*f6dc9357SAndroid Build Coastguard Worker {
1105*f6dc9357SAndroid Build Coastguard Worker if (name.Len() != 2)
1106*f6dc9357SAndroid Build Coastguard Worker {
1107*f6dc9357SAndroid Build Coastguard Worker name.DeleteBack();
1108*f6dc9357SAndroid Build Coastguard Worker str = name.Ptr(1);
1109*f6dc9357SAndroid Build Coastguard Worker }
1110*f6dc9357SAndroid Build Coastguard Worker }
1111*f6dc9357SAndroid Build Coastguard Worker else if (!name.IsEmpty())
1112*f6dc9357SAndroid Build Coastguard Worker str = name;
1113*f6dc9357SAndroid Build Coastguard Worker s += str;
1114*f6dc9357SAndroid Build Coastguard Worker return;
1115*f6dc9357SAndroid Build Coastguard Worker }
1116*f6dc9357SAndroid Build Coastguard Worker }
1117*f6dc9357SAndroid Build Coastguard Worker s.Add_UInt32(id);
1118*f6dc9357SAndroid Build Coastguard Worker }
1119*f6dc9357SAndroid Build Coastguard Worker
1120*f6dc9357SAndroid Build Coastguard Worker void CHandler::AddLangPrefix(UString &s, UInt32 lang) const
1121*f6dc9357SAndroid Build Coastguard Worker {
1122*f6dc9357SAndroid Build Coastguard Worker if (!_oneLang)
1123*f6dc9357SAndroid Build Coastguard Worker {
1124*f6dc9357SAndroid Build Coastguard Worker AddResNameToString(s, lang);
1125*f6dc9357SAndroid Build Coastguard Worker s.Add_PathSepar();
1126*f6dc9357SAndroid Build Coastguard Worker }
1127*f6dc9357SAndroid Build Coastguard Worker }
1128*f6dc9357SAndroid Build Coastguard Worker
1129*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))
1130*f6dc9357SAndroid Build Coastguard Worker {
1131*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
1132*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop;
1133*f6dc9357SAndroid Build Coastguard Worker const CMixItem &mixItem = _mixItems[index];
1134*f6dc9357SAndroid Build Coastguard Worker if (mixItem.StringIndex >= 0)
1135*f6dc9357SAndroid Build Coastguard Worker {
1136*f6dc9357SAndroid Build Coastguard Worker const CStringItem &item = _strings[mixItem.StringIndex];
1137*f6dc9357SAndroid Build Coastguard Worker switch (propID)
1138*f6dc9357SAndroid Build Coastguard Worker {
1139*f6dc9357SAndroid Build Coastguard Worker case kpidPath:
1140*f6dc9357SAndroid Build Coastguard Worker {
1141*f6dc9357SAndroid Build Coastguard Worker UString s = _resourcesPrefix;
1142*f6dc9357SAndroid Build Coastguard Worker AddLangPrefix(s, item.Lang);
1143*f6dc9357SAndroid Build Coastguard Worker s += "string.txt";
1144*f6dc9357SAndroid Build Coastguard Worker prop = s;
1145*f6dc9357SAndroid Build Coastguard Worker break;
1146*f6dc9357SAndroid Build Coastguard Worker }
1147*f6dc9357SAndroid Build Coastguard Worker case kpidSize:
1148*f6dc9357SAndroid Build Coastguard Worker case kpidPackSize:
1149*f6dc9357SAndroid Build Coastguard Worker prop = (UInt64)item.FinalSize(); break;
1150*f6dc9357SAndroid Build Coastguard Worker }
1151*f6dc9357SAndroid Build Coastguard Worker }
1152*f6dc9357SAndroid Build Coastguard Worker else if (mixItem.VersionIndex >= 0)
1153*f6dc9357SAndroid Build Coastguard Worker {
1154*f6dc9357SAndroid Build Coastguard Worker const CByteBuffer_WithLang &item = _versionFiles[mixItem.VersionIndex];
1155*f6dc9357SAndroid Build Coastguard Worker switch (propID)
1156*f6dc9357SAndroid Build Coastguard Worker {
1157*f6dc9357SAndroid Build Coastguard Worker case kpidPath:
1158*f6dc9357SAndroid Build Coastguard Worker {
1159*f6dc9357SAndroid Build Coastguard Worker UString s = _resourcesPrefix;
1160*f6dc9357SAndroid Build Coastguard Worker AddLangPrefix(s, item.Lang);
1161*f6dc9357SAndroid Build Coastguard Worker s += "version.txt";
1162*f6dc9357SAndroid Build Coastguard Worker prop = s;
1163*f6dc9357SAndroid Build Coastguard Worker break;
1164*f6dc9357SAndroid Build Coastguard Worker }
1165*f6dc9357SAndroid Build Coastguard Worker case kpidSize:
1166*f6dc9357SAndroid Build Coastguard Worker case kpidPackSize:
1167*f6dc9357SAndroid Build Coastguard Worker prop = (UInt64)item.Size(); break;
1168*f6dc9357SAndroid Build Coastguard Worker }
1169*f6dc9357SAndroid Build Coastguard Worker }
1170*f6dc9357SAndroid Build Coastguard Worker else if (mixItem.ResourceIndex >= 0)
1171*f6dc9357SAndroid Build Coastguard Worker {
1172*f6dc9357SAndroid Build Coastguard Worker const CResItem &item = _items[mixItem.ResourceIndex];
1173*f6dc9357SAndroid Build Coastguard Worker switch (propID)
1174*f6dc9357SAndroid Build Coastguard Worker {
1175*f6dc9357SAndroid Build Coastguard Worker case kpidPath:
1176*f6dc9357SAndroid Build Coastguard Worker {
1177*f6dc9357SAndroid Build Coastguard Worker UString s = _resourcesPrefix;
1178*f6dc9357SAndroid Build Coastguard Worker AddLangPrefix(s, item.Lang);
1179*f6dc9357SAndroid Build Coastguard Worker {
1180*f6dc9357SAndroid Build Coastguard Worker const char *p = NULL;
1181*f6dc9357SAndroid Build Coastguard Worker if (item.Type < Z7_ARRAY_SIZE(g_ResTypes))
1182*f6dc9357SAndroid Build Coastguard Worker p = g_ResTypes[item.Type];
1183*f6dc9357SAndroid Build Coastguard Worker if (p)
1184*f6dc9357SAndroid Build Coastguard Worker s += p;
1185*f6dc9357SAndroid Build Coastguard Worker else
1186*f6dc9357SAndroid Build Coastguard Worker AddResNameToString(s, item.Type);
1187*f6dc9357SAndroid Build Coastguard Worker }
1188*f6dc9357SAndroid Build Coastguard Worker s.Add_PathSepar();
1189*f6dc9357SAndroid Build Coastguard Worker AddResNameToString(s, item.ID);
1190*f6dc9357SAndroid Build Coastguard Worker if (item.HeaderSize != 0)
1191*f6dc9357SAndroid Build Coastguard Worker {
1192*f6dc9357SAndroid Build Coastguard Worker if (item.IsBmp())
1193*f6dc9357SAndroid Build Coastguard Worker s += ".bmp";
1194*f6dc9357SAndroid Build Coastguard Worker else if (item.IsIcon())
1195*f6dc9357SAndroid Build Coastguard Worker s += ".ico";
1196*f6dc9357SAndroid Build Coastguard Worker }
1197*f6dc9357SAndroid Build Coastguard Worker prop = s;
1198*f6dc9357SAndroid Build Coastguard Worker break;
1199*f6dc9357SAndroid Build Coastguard Worker }
1200*f6dc9357SAndroid Build Coastguard Worker case kpidSize: prop = (UInt64)item.GetSize(); break;
1201*f6dc9357SAndroid Build Coastguard Worker case kpidPackSize: prop = (UInt64)item.Size; break;
1202*f6dc9357SAndroid Build Coastguard Worker }
1203*f6dc9357SAndroid Build Coastguard Worker }
1204*f6dc9357SAndroid Build Coastguard Worker else
1205*f6dc9357SAndroid Build Coastguard Worker {
1206*f6dc9357SAndroid Build Coastguard Worker const CSection &item = _sections[mixItem.SectionIndex];
1207*f6dc9357SAndroid Build Coastguard Worker switch (propID)
1208*f6dc9357SAndroid Build Coastguard Worker {
1209*f6dc9357SAndroid Build Coastguard Worker case kpidPath:
1210*f6dc9357SAndroid Build Coastguard Worker {
1211*f6dc9357SAndroid Build Coastguard Worker AString s = item.Name;
1212*f6dc9357SAndroid Build Coastguard Worker s.Replace('/', '_');
1213*f6dc9357SAndroid Build Coastguard Worker s.Replace('\\', '_');
1214*f6dc9357SAndroid Build Coastguard Worker prop = MultiByteToUnicodeString(s);
1215*f6dc9357SAndroid Build Coastguard Worker break;
1216*f6dc9357SAndroid Build Coastguard Worker }
1217*f6dc9357SAndroid Build Coastguard Worker case kpidSize: prop = (UInt64)item.GetSize_Extract(); break;
1218*f6dc9357SAndroid Build Coastguard Worker // case kpid_NumRelocs: prop = (UInt32)item.NumRelocs; break;
1219*f6dc9357SAndroid Build Coastguard Worker case kpidPackSize: prop = (UInt64)item.PSize; break;
1220*f6dc9357SAndroid Build Coastguard Worker case kpidVirtualSize: prop = (UInt64)item.VSize; break;
1221*f6dc9357SAndroid Build Coastguard Worker case kpidOffset: prop = item.Pa; break;
1222*f6dc9357SAndroid Build Coastguard Worker case kpidVa: if (item.IsRealSect) prop = item.Va; break;
1223*f6dc9357SAndroid Build Coastguard Worker case kpidMTime:
1224*f6dc9357SAndroid Build Coastguard Worker case kpidCTime:
1225*f6dc9357SAndroid Build Coastguard Worker TimeToProp(item.IsDebug ? item.Time : _header.Time, prop); break;
1226*f6dc9357SAndroid Build Coastguard Worker case kpidCharacts:
1227*f6dc9357SAndroid Build Coastguard Worker if (item.IsRealSect)
1228*f6dc9357SAndroid Build Coastguard Worker {
1229*f6dc9357SAndroid Build Coastguard Worker UInt32 flags = item.Flags;
1230*f6dc9357SAndroid Build Coastguard Worker const UInt32 MY_IMAGE_SCN_ALIGN_MASK = 0x00F00000;
1231*f6dc9357SAndroid Build Coastguard Worker AString s = FlagsToString(g_SectFlags, Z7_ARRAY_SIZE(g_SectFlags), item.Flags & ~MY_IMAGE_SCN_ALIGN_MASK);
1232*f6dc9357SAndroid Build Coastguard Worker const UInt32 align = ((flags >> 20) & 0xF);
1233*f6dc9357SAndroid Build Coastguard Worker if (align != 0)
1234*f6dc9357SAndroid Build Coastguard Worker {
1235*f6dc9357SAndroid Build Coastguard Worker char sz[32];
1236*f6dc9357SAndroid Build Coastguard Worker ConvertUInt32ToString(1 << (align - 1), sz);
1237*f6dc9357SAndroid Build Coastguard Worker s.Add_Space();
1238*f6dc9357SAndroid Build Coastguard Worker s += "align_";
1239*f6dc9357SAndroid Build Coastguard Worker s += sz;
1240*f6dc9357SAndroid Build Coastguard Worker }
1241*f6dc9357SAndroid Build Coastguard Worker prop = s;
1242*f6dc9357SAndroid Build Coastguard Worker }
1243*f6dc9357SAndroid Build Coastguard Worker break;
1244*f6dc9357SAndroid Build Coastguard Worker case kpidZerosTailIsAllowed: if (!item.IsRealSect) prop = true; break;
1245*f6dc9357SAndroid Build Coastguard Worker }
1246*f6dc9357SAndroid Build Coastguard Worker }
1247*f6dc9357SAndroid Build Coastguard Worker prop.Detach(value);
1248*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1249*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
1250*f6dc9357SAndroid Build Coastguard Worker }
1251*f6dc9357SAndroid Build Coastguard Worker
1252*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::LoadDebugSections(IInStream *stream, bool &thereIsSection)
1253*f6dc9357SAndroid Build Coastguard Worker {
1254*f6dc9357SAndroid Build Coastguard Worker thereIsSection = false;
1255*f6dc9357SAndroid Build Coastguard Worker const CDirLink &debugLink = _optHeader.DirItems[kDirLink_Debug];
1256*f6dc9357SAndroid Build Coastguard Worker if (debugLink.Size == 0)
1257*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1258*f6dc9357SAndroid Build Coastguard Worker const unsigned kEntrySize = 28;
1259*f6dc9357SAndroid Build Coastguard Worker UInt32 numItems = debugLink.Size / kEntrySize;
1260*f6dc9357SAndroid Build Coastguard Worker if (numItems > 16)
1261*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1262*f6dc9357SAndroid Build Coastguard Worker
1263*f6dc9357SAndroid Build Coastguard Worker // MAC's EFI file: numItems can be incorrect. Only first CDebugEntry entry is correct.
1264*f6dc9357SAndroid Build Coastguard Worker // debugLink.Size = kEntrySize + some_data, pointed by entry[0].
1265*f6dc9357SAndroid Build Coastguard Worker if (numItems * kEntrySize != debugLink.Size)
1266*f6dc9357SAndroid Build Coastguard Worker {
1267*f6dc9357SAndroid Build Coastguard Worker // return S_FALSE;
1268*f6dc9357SAndroid Build Coastguard Worker if (numItems > 1)
1269*f6dc9357SAndroid Build Coastguard Worker numItems = 1;
1270*f6dc9357SAndroid Build Coastguard Worker }
1271*f6dc9357SAndroid Build Coastguard Worker
1272*f6dc9357SAndroid Build Coastguard Worker UInt64 pa = 0;
1273*f6dc9357SAndroid Build Coastguard Worker unsigned i;
1274*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < _sections.Size(); i++)
1275*f6dc9357SAndroid Build Coastguard Worker {
1276*f6dc9357SAndroid Build Coastguard Worker const CSection § = _sections[i];
1277*f6dc9357SAndroid Build Coastguard Worker if (sect.Va <= debugLink.Va && debugLink.Va + debugLink.Size <= sect.Va + sect.PSize)
1278*f6dc9357SAndroid Build Coastguard Worker {
1279*f6dc9357SAndroid Build Coastguard Worker pa = sect.Pa + (debugLink.Va - sect.Va);
1280*f6dc9357SAndroid Build Coastguard Worker break;
1281*f6dc9357SAndroid Build Coastguard Worker }
1282*f6dc9357SAndroid Build Coastguard Worker }
1283*f6dc9357SAndroid Build Coastguard Worker if (i == _sections.Size())
1284*f6dc9357SAndroid Build Coastguard Worker {
1285*f6dc9357SAndroid Build Coastguard Worker // Exe for ARM requires S_OK
1286*f6dc9357SAndroid Build Coastguard Worker // return S_FALSE;
1287*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1288*f6dc9357SAndroid Build Coastguard Worker }
1289*f6dc9357SAndroid Build Coastguard Worker
1290*f6dc9357SAndroid Build Coastguard Worker CByteBuffer buffer(debugLink.Size);
1291*f6dc9357SAndroid Build Coastguard Worker Byte *buf = buffer;
1292*f6dc9357SAndroid Build Coastguard Worker
1293*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekSet(stream, pa))
1294*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(stream, buf, debugLink.Size))
1295*f6dc9357SAndroid Build Coastguard Worker
1296*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < numItems; i++)
1297*f6dc9357SAndroid Build Coastguard Worker {
1298*f6dc9357SAndroid Build Coastguard Worker CDebugEntry de;
1299*f6dc9357SAndroid Build Coastguard Worker de.Parse(buf);
1300*f6dc9357SAndroid Build Coastguard Worker
1301*f6dc9357SAndroid Build Coastguard Worker if (de.Size == 0)
1302*f6dc9357SAndroid Build Coastguard Worker continue;
1303*f6dc9357SAndroid Build Coastguard Worker
1304*f6dc9357SAndroid Build Coastguard Worker UInt32 totalSize = de.Pa + de.Size;
1305*f6dc9357SAndroid Build Coastguard Worker if (totalSize > _totalSize)
1306*f6dc9357SAndroid Build Coastguard Worker {
1307*f6dc9357SAndroid Build Coastguard Worker _totalSize = totalSize;
1308*f6dc9357SAndroid Build Coastguard Worker thereIsSection = true;
1309*f6dc9357SAndroid Build Coastguard Worker
1310*f6dc9357SAndroid Build Coastguard Worker CSection § = _sections.AddNew();
1311*f6dc9357SAndroid Build Coastguard Worker sect.Name = ".debug";
1312*f6dc9357SAndroid Build Coastguard Worker sect.Name.Add_UInt32(i);
1313*f6dc9357SAndroid Build Coastguard Worker sect.IsDebug = true;
1314*f6dc9357SAndroid Build Coastguard Worker sect.Time = de.Time;
1315*f6dc9357SAndroid Build Coastguard Worker sect.Va = de.Va;
1316*f6dc9357SAndroid Build Coastguard Worker sect.Pa = de.Pa;
1317*f6dc9357SAndroid Build Coastguard Worker sect.Set_Size_for_all(de.Size);
1318*f6dc9357SAndroid Build Coastguard Worker }
1319*f6dc9357SAndroid Build Coastguard Worker buf += kEntrySize;
1320*f6dc9357SAndroid Build Coastguard Worker }
1321*f6dc9357SAndroid Build Coastguard Worker
1322*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1323*f6dc9357SAndroid Build Coastguard Worker }
1324*f6dc9357SAndroid Build Coastguard Worker
1325*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::ReadTable(UInt32 offset, CRecordVector<CTableItem> &items)
1326*f6dc9357SAndroid Build Coastguard Worker {
1327*f6dc9357SAndroid Build Coastguard Worker if ((offset & 3) != 0 || offset >= _buf.Size())
1328*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1329*f6dc9357SAndroid Build Coastguard Worker size_t rem = _buf.Size() - offset;
1330*f6dc9357SAndroid Build Coastguard Worker if (rem < 16)
1331*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1332*f6dc9357SAndroid Build Coastguard Worker unsigned numNameItems = Get16(_buf + offset + 12);
1333*f6dc9357SAndroid Build Coastguard Worker unsigned numIdItems = Get16(_buf + offset + 14);
1334*f6dc9357SAndroid Build Coastguard Worker unsigned numItems = numNameItems + numIdItems;
1335*f6dc9357SAndroid Build Coastguard Worker if ((rem - 16) / 8 < numItems)
1336*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1337*f6dc9357SAndroid Build Coastguard Worker if (!_usedRes.SetRange(offset, 16 + numItems * 8))
1338*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1339*f6dc9357SAndroid Build Coastguard Worker offset += 16;
1340*f6dc9357SAndroid Build Coastguard Worker items.ClearAndReserve(numItems);
1341*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < numItems; i++, offset += 8)
1342*f6dc9357SAndroid Build Coastguard Worker {
1343*f6dc9357SAndroid Build Coastguard Worker const Byte *buf = _buf + offset;
1344*f6dc9357SAndroid Build Coastguard Worker CTableItem item;
1345*f6dc9357SAndroid Build Coastguard Worker item.ID = Get32(buf + 0);
1346*f6dc9357SAndroid Build Coastguard Worker if ((bool)((item.ID & kFlag) != 0) != (bool)(i < numNameItems))
1347*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1348*f6dc9357SAndroid Build Coastguard Worker item.Offset = Get32(buf + 4);
1349*f6dc9357SAndroid Build Coastguard Worker items.AddInReserved(item);
1350*f6dc9357SAndroid Build Coastguard Worker }
1351*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1352*f6dc9357SAndroid Build Coastguard Worker }
1353*f6dc9357SAndroid Build Coastguard Worker
1354*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kFileSizeMax = (UInt32)1 << 31;
1355*f6dc9357SAndroid Build Coastguard Worker static const unsigned kNumResItemsMax = (unsigned)1 << 23;
1356*f6dc9357SAndroid Build Coastguard Worker static const unsigned kNumStringLangsMax = 256;
1357*f6dc9357SAndroid Build Coastguard Worker
1358*f6dc9357SAndroid Build Coastguard Worker // BITMAPINFOHEADER
1359*f6dc9357SAndroid Build Coastguard Worker struct CBitmapInfoHeader
1360*f6dc9357SAndroid Build Coastguard Worker {
1361*f6dc9357SAndroid Build Coastguard Worker // UInt32 HeaderSize;
1362*f6dc9357SAndroid Build Coastguard Worker UInt32 XSize;
1363*f6dc9357SAndroid Build Coastguard Worker Int32 YSize;
1364*f6dc9357SAndroid Build Coastguard Worker UInt16 Planes;
1365*f6dc9357SAndroid Build Coastguard Worker UInt16 BitCount;
1366*f6dc9357SAndroid Build Coastguard Worker UInt32 Compression;
1367*f6dc9357SAndroid Build Coastguard Worker UInt32 SizeImage;
1368*f6dc9357SAndroid Build Coastguard Worker
1369*f6dc9357SAndroid Build Coastguard Worker bool Parse(const Byte *p, size_t size);
1370*f6dc9357SAndroid Build Coastguard Worker };
1371*f6dc9357SAndroid Build Coastguard Worker
1372*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kBitmapInfoHeader_Size = 0x28;
1373*f6dc9357SAndroid Build Coastguard Worker
1374*f6dc9357SAndroid Build Coastguard Worker bool CBitmapInfoHeader::Parse(const Byte *p, size_t size)
1375*f6dc9357SAndroid Build Coastguard Worker {
1376*f6dc9357SAndroid Build Coastguard Worker if (size < kBitmapInfoHeader_Size || Get32(p) != kBitmapInfoHeader_Size)
1377*f6dc9357SAndroid Build Coastguard Worker return false;
1378*f6dc9357SAndroid Build Coastguard Worker G32( 4, XSize);
1379*f6dc9357SAndroid Build Coastguard Worker G32_signed( 8, YSize);
1380*f6dc9357SAndroid Build Coastguard Worker G16(12, Planes);
1381*f6dc9357SAndroid Build Coastguard Worker G16(14, BitCount);
1382*f6dc9357SAndroid Build Coastguard Worker G32(16, Compression);
1383*f6dc9357SAndroid Build Coastguard Worker G32(20, SizeImage);
1384*f6dc9357SAndroid Build Coastguard Worker return true;
1385*f6dc9357SAndroid Build Coastguard Worker }
1386*f6dc9357SAndroid Build Coastguard Worker
1387*f6dc9357SAndroid Build Coastguard Worker static UInt32 GetImageSize(UInt32 xSize, UInt32 ySize, UInt32 bitCount)
1388*f6dc9357SAndroid Build Coastguard Worker {
1389*f6dc9357SAndroid Build Coastguard Worker return ((xSize * bitCount + 7) / 8 + 3) / 4 * 4 * ySize;
1390*f6dc9357SAndroid Build Coastguard Worker }
1391*f6dc9357SAndroid Build Coastguard Worker
1392*f6dc9357SAndroid Build Coastguard Worker static UInt32 SetBitmapHeader(Byte *dest, const Byte *src, UInt32 size)
1393*f6dc9357SAndroid Build Coastguard Worker {
1394*f6dc9357SAndroid Build Coastguard Worker CBitmapInfoHeader h;
1395*f6dc9357SAndroid Build Coastguard Worker if (!h.Parse(src, size))
1396*f6dc9357SAndroid Build Coastguard Worker return 0;
1397*f6dc9357SAndroid Build Coastguard Worker if (h.YSize < 0)
1398*f6dc9357SAndroid Build Coastguard Worker h.YSize = -h.YSize;
1399*f6dc9357SAndroid Build Coastguard Worker if (h.XSize > (1 << 26)
1400*f6dc9357SAndroid Build Coastguard Worker || h.YSize > (1 << 26)
1401*f6dc9357SAndroid Build Coastguard Worker || h.YSize < 0
1402*f6dc9357SAndroid Build Coastguard Worker || h.Planes != 1 || h.BitCount > 32)
1403*f6dc9357SAndroid Build Coastguard Worker return 0;
1404*f6dc9357SAndroid Build Coastguard Worker if (h.SizeImage == 0)
1405*f6dc9357SAndroid Build Coastguard Worker {
1406*f6dc9357SAndroid Build Coastguard Worker if (h.Compression != 0) // BI_RGB
1407*f6dc9357SAndroid Build Coastguard Worker return 0;
1408*f6dc9357SAndroid Build Coastguard Worker h.SizeImage = GetImageSize(h.XSize, (UInt32)h.YSize, h.BitCount);
1409*f6dc9357SAndroid Build Coastguard Worker }
1410*f6dc9357SAndroid Build Coastguard Worker UInt32 totalSize = kBmpHeaderSize + size;
1411*f6dc9357SAndroid Build Coastguard Worker UInt32 offBits = totalSize - h.SizeImage;
1412*f6dc9357SAndroid Build Coastguard Worker // BITMAPFILEHEADER
1413*f6dc9357SAndroid Build Coastguard Worker SetUi16(dest, 0x4D42)
1414*f6dc9357SAndroid Build Coastguard Worker SetUi32(dest + 2, totalSize)
1415*f6dc9357SAndroid Build Coastguard Worker SetUi32(dest + 6, 0)
1416*f6dc9357SAndroid Build Coastguard Worker SetUi32(dest + 10, offBits)
1417*f6dc9357SAndroid Build Coastguard Worker return kBmpHeaderSize;
1418*f6dc9357SAndroid Build Coastguard Worker }
1419*f6dc9357SAndroid Build Coastguard Worker
1420*f6dc9357SAndroid Build Coastguard Worker static UInt32 SetIconHeader(Byte *dest, const Byte *src, UInt32 size)
1421*f6dc9357SAndroid Build Coastguard Worker {
1422*f6dc9357SAndroid Build Coastguard Worker CBitmapInfoHeader h;
1423*f6dc9357SAndroid Build Coastguard Worker if (!h.Parse(src, size))
1424*f6dc9357SAndroid Build Coastguard Worker return 0;
1425*f6dc9357SAndroid Build Coastguard Worker if (h.YSize < 0)
1426*f6dc9357SAndroid Build Coastguard Worker h.YSize = -h.YSize;
1427*f6dc9357SAndroid Build Coastguard Worker if (h.XSize > (1 << 26)
1428*f6dc9357SAndroid Build Coastguard Worker || h.YSize > (1 << 26)
1429*f6dc9357SAndroid Build Coastguard Worker || h.YSize < 0
1430*f6dc9357SAndroid Build Coastguard Worker || h.Planes != 1
1431*f6dc9357SAndroid Build Coastguard Worker || h.Compression != 0) // BI_RGB
1432*f6dc9357SAndroid Build Coastguard Worker return 0;
1433*f6dc9357SAndroid Build Coastguard Worker
1434*f6dc9357SAndroid Build Coastguard Worker const UInt32 numBitCount = h.BitCount;
1435*f6dc9357SAndroid Build Coastguard Worker if (numBitCount != 1 &&
1436*f6dc9357SAndroid Build Coastguard Worker numBitCount != 4 &&
1437*f6dc9357SAndroid Build Coastguard Worker numBitCount != 8 &&
1438*f6dc9357SAndroid Build Coastguard Worker numBitCount != 24 &&
1439*f6dc9357SAndroid Build Coastguard Worker numBitCount != 32)
1440*f6dc9357SAndroid Build Coastguard Worker return 0;
1441*f6dc9357SAndroid Build Coastguard Worker
1442*f6dc9357SAndroid Build Coastguard Worker if ((h.YSize & 1) != 0)
1443*f6dc9357SAndroid Build Coastguard Worker return 0;
1444*f6dc9357SAndroid Build Coastguard Worker h.YSize /= 2;
1445*f6dc9357SAndroid Build Coastguard Worker if (h.XSize > 0x100 || h.YSize > 0x100)
1446*f6dc9357SAndroid Build Coastguard Worker return 0;
1447*f6dc9357SAndroid Build Coastguard Worker
1448*f6dc9357SAndroid Build Coastguard Worker UInt32 imageSize;
1449*f6dc9357SAndroid Build Coastguard Worker // imageSize is not correct if AND mask array contains zeros
1450*f6dc9357SAndroid Build Coastguard Worker // in this case it is equal image1Size
1451*f6dc9357SAndroid Build Coastguard Worker
1452*f6dc9357SAndroid Build Coastguard Worker // UInt32 imageSize = h.SizeImage;
1453*f6dc9357SAndroid Build Coastguard Worker // if (imageSize == 0)
1454*f6dc9357SAndroid Build Coastguard Worker // {
1455*f6dc9357SAndroid Build Coastguard Worker const UInt32 image1Size = GetImageSize(h.XSize, (UInt32)h.YSize, h.BitCount);
1456*f6dc9357SAndroid Build Coastguard Worker const UInt32 image2Size = GetImageSize(h.XSize, (UInt32)h.YSize, 1);
1457*f6dc9357SAndroid Build Coastguard Worker imageSize = image1Size + image2Size;
1458*f6dc9357SAndroid Build Coastguard Worker // }
1459*f6dc9357SAndroid Build Coastguard Worker UInt32 numColors = 0;
1460*f6dc9357SAndroid Build Coastguard Worker if (numBitCount < 16)
1461*f6dc9357SAndroid Build Coastguard Worker numColors = 1 << numBitCount;
1462*f6dc9357SAndroid Build Coastguard Worker
1463*f6dc9357SAndroid Build Coastguard Worker SetUi16(dest, 0) // Reserved
1464*f6dc9357SAndroid Build Coastguard Worker SetUi16(dest + 2, 1) // RES_ICON
1465*f6dc9357SAndroid Build Coastguard Worker SetUi16(dest + 4, 1) // ResCount
1466*f6dc9357SAndroid Build Coastguard Worker
1467*f6dc9357SAndroid Build Coastguard Worker dest[6] = (Byte)h.XSize; // Width
1468*f6dc9357SAndroid Build Coastguard Worker dest[7] = (Byte)h.YSize; // Height
1469*f6dc9357SAndroid Build Coastguard Worker dest[8] = (Byte)numColors; // ColorCount
1470*f6dc9357SAndroid Build Coastguard Worker dest[9] = 0; // Reserved
1471*f6dc9357SAndroid Build Coastguard Worker
1472*f6dc9357SAndroid Build Coastguard Worker SetUi32(dest + 10, 0) // Reserved1 / Reserved2
1473*f6dc9357SAndroid Build Coastguard Worker
1474*f6dc9357SAndroid Build Coastguard Worker UInt32 numQuadsBytes = numColors * 4;
1475*f6dc9357SAndroid Build Coastguard Worker UInt32 BytesInRes = kBitmapInfoHeader_Size + numQuadsBytes + imageSize;
1476*f6dc9357SAndroid Build Coastguard Worker SetUi32(dest + 14, BytesInRes)
1477*f6dc9357SAndroid Build Coastguard Worker SetUi32(dest + 18, kIconHeaderSize)
1478*f6dc9357SAndroid Build Coastguard Worker
1479*f6dc9357SAndroid Build Coastguard Worker /*
1480*f6dc9357SAndroid Build Coastguard Worker Description = DWORDToString(xSize) +
1481*f6dc9357SAndroid Build Coastguard Worker kDelimiterChar + DWORDToString(ySize) +
1482*f6dc9357SAndroid Build Coastguard Worker kDelimiterChar + DWORDToString(numBitCount);
1483*f6dc9357SAndroid Build Coastguard Worker */
1484*f6dc9357SAndroid Build Coastguard Worker return kIconHeaderSize;
1485*f6dc9357SAndroid Build Coastguard Worker }
1486*f6dc9357SAndroid Build Coastguard Worker
1487*f6dc9357SAndroid Build Coastguard Worker bool CHandler::ParseStringRes(UInt32 id, UInt32 lang, const Byte *src, UInt32 size)
1488*f6dc9357SAndroid Build Coastguard Worker {
1489*f6dc9357SAndroid Build Coastguard Worker if ((size & 1) != 0)
1490*f6dc9357SAndroid Build Coastguard Worker return false;
1491*f6dc9357SAndroid Build Coastguard Worker
1492*f6dc9357SAndroid Build Coastguard Worker unsigned i;
1493*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < _strings.Size(); i++)
1494*f6dc9357SAndroid Build Coastguard Worker if (_strings[i].Lang == lang)
1495*f6dc9357SAndroid Build Coastguard Worker break;
1496*f6dc9357SAndroid Build Coastguard Worker if (i == _strings.Size())
1497*f6dc9357SAndroid Build Coastguard Worker {
1498*f6dc9357SAndroid Build Coastguard Worker if (_strings.Size() >= kNumStringLangsMax)
1499*f6dc9357SAndroid Build Coastguard Worker return false;
1500*f6dc9357SAndroid Build Coastguard Worker CStringItem &item = _strings.AddNew();
1501*f6dc9357SAndroid Build Coastguard Worker item.Lang = lang;
1502*f6dc9357SAndroid Build Coastguard Worker }
1503*f6dc9357SAndroid Build Coastguard Worker
1504*f6dc9357SAndroid Build Coastguard Worker CStringItem &item = _strings[i];
1505*f6dc9357SAndroid Build Coastguard Worker id = (id - 1) << 4;
1506*f6dc9357SAndroid Build Coastguard Worker UInt32 pos = 0;
1507*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < 16; i++)
1508*f6dc9357SAndroid Build Coastguard Worker {
1509*f6dc9357SAndroid Build Coastguard Worker if (size - pos < 2)
1510*f6dc9357SAndroid Build Coastguard Worker return false;
1511*f6dc9357SAndroid Build Coastguard Worker UInt32 len = Get16(src + pos);
1512*f6dc9357SAndroid Build Coastguard Worker pos += 2;
1513*f6dc9357SAndroid Build Coastguard Worker if (len != 0)
1514*f6dc9357SAndroid Build Coastguard Worker {
1515*f6dc9357SAndroid Build Coastguard Worker if (size - pos < len * 2)
1516*f6dc9357SAndroid Build Coastguard Worker return false;
1517*f6dc9357SAndroid Build Coastguard Worker char temp[32];
1518*f6dc9357SAndroid Build Coastguard Worker ConvertUInt32ToString(id + i, temp);
1519*f6dc9357SAndroid Build Coastguard Worker size_t tempLen = strlen(temp);
1520*f6dc9357SAndroid Build Coastguard Worker size_t j;
1521*f6dc9357SAndroid Build Coastguard Worker for (j = 0; j < tempLen; j++)
1522*f6dc9357SAndroid Build Coastguard Worker item.AddChar(temp[j]);
1523*f6dc9357SAndroid Build Coastguard Worker item.AddChar('\t');
1524*f6dc9357SAndroid Build Coastguard Worker for (j = 0; j < len; j++, pos += 2)
1525*f6dc9357SAndroid Build Coastguard Worker item.AddWChar_Smart(Get16(src + pos));
1526*f6dc9357SAndroid Build Coastguard Worker item.NewLine();
1527*f6dc9357SAndroid Build Coastguard Worker }
1528*f6dc9357SAndroid Build Coastguard Worker }
1529*f6dc9357SAndroid Build Coastguard Worker if (size == pos)
1530*f6dc9357SAndroid Build Coastguard Worker return true;
1531*f6dc9357SAndroid Build Coastguard Worker
1532*f6dc9357SAndroid Build Coastguard Worker // Some rare case files have additional ZERO.
1533*f6dc9357SAndroid Build Coastguard Worker if (size == pos + 2 && Get16(src + pos) == 0)
1534*f6dc9357SAndroid Build Coastguard Worker return true;
1535*f6dc9357SAndroid Build Coastguard Worker
1536*f6dc9357SAndroid Build Coastguard Worker return false;
1537*f6dc9357SAndroid Build Coastguard Worker }
1538*f6dc9357SAndroid Build Coastguard Worker
1539*f6dc9357SAndroid Build Coastguard Worker
1540*f6dc9357SAndroid Build Coastguard Worker // ---------- VERSION ----------
1541*f6dc9357SAndroid Build Coastguard Worker
1542*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kMy_VS_FFI_SIGNATURE = 0xFEEF04BD;
1543*f6dc9357SAndroid Build Coastguard Worker
1544*f6dc9357SAndroid Build Coastguard Worker struct CMy_VS_FIXEDFILEINFO
1545*f6dc9357SAndroid Build Coastguard Worker {
1546*f6dc9357SAndroid Build Coastguard Worker // UInt32 Signature;
1547*f6dc9357SAndroid Build Coastguard Worker // UInt32 StrucVersion;
1548*f6dc9357SAndroid Build Coastguard Worker UInt32 VersionMS;
1549*f6dc9357SAndroid Build Coastguard Worker UInt32 VersionLS;
1550*f6dc9357SAndroid Build Coastguard Worker UInt32 ProductVersionMS;
1551*f6dc9357SAndroid Build Coastguard Worker UInt32 ProductVersionLS;
1552*f6dc9357SAndroid Build Coastguard Worker UInt32 FlagsMask;
1553*f6dc9357SAndroid Build Coastguard Worker UInt32 Flags;
1554*f6dc9357SAndroid Build Coastguard Worker UInt32 OS;
1555*f6dc9357SAndroid Build Coastguard Worker UInt32 Type;
1556*f6dc9357SAndroid Build Coastguard Worker UInt32 Subtype;
1557*f6dc9357SAndroid Build Coastguard Worker UInt32 DateMS;
1558*f6dc9357SAndroid Build Coastguard Worker UInt32 DateLS;
1559*f6dc9357SAndroid Build Coastguard Worker
1560*f6dc9357SAndroid Build Coastguard Worker bool Parse(const Byte *p);
1561*f6dc9357SAndroid Build Coastguard Worker void PrintToTextFile(CTextFile &f, CObjectVector<CStringKeyValue> &keys);
1562*f6dc9357SAndroid Build Coastguard Worker };
1563*f6dc9357SAndroid Build Coastguard Worker
1564*f6dc9357SAndroid Build Coastguard Worker bool CMy_VS_FIXEDFILEINFO::Parse(const Byte *p)
1565*f6dc9357SAndroid Build Coastguard Worker {
1566*f6dc9357SAndroid Build Coastguard Worker if (Get32(p) != kMy_VS_FFI_SIGNATURE) // signature;
1567*f6dc9357SAndroid Build Coastguard Worker return false;
1568*f6dc9357SAndroid Build Coastguard Worker // G32(0x04, StrucVersion);
1569*f6dc9357SAndroid Build Coastguard Worker G32(0x08, VersionMS);
1570*f6dc9357SAndroid Build Coastguard Worker G32(0x0C, VersionLS);
1571*f6dc9357SAndroid Build Coastguard Worker G32(0x10, ProductVersionMS);
1572*f6dc9357SAndroid Build Coastguard Worker G32(0x14, ProductVersionLS);
1573*f6dc9357SAndroid Build Coastguard Worker G32(0x18, FlagsMask);
1574*f6dc9357SAndroid Build Coastguard Worker G32(0x1C, Flags);
1575*f6dc9357SAndroid Build Coastguard Worker G32(0x20, OS);
1576*f6dc9357SAndroid Build Coastguard Worker G32(0x24, Type);
1577*f6dc9357SAndroid Build Coastguard Worker G32(0x28, Subtype);
1578*f6dc9357SAndroid Build Coastguard Worker G32(0x2C, DateMS);
1579*f6dc9357SAndroid Build Coastguard Worker G32(0x40, DateLS);
1580*f6dc9357SAndroid Build Coastguard Worker return true;
1581*f6dc9357SAndroid Build Coastguard Worker }
1582*f6dc9357SAndroid Build Coastguard Worker
1583*f6dc9357SAndroid Build Coastguard Worker static void PrintUInt32(CTextFile &f, UInt32 v)
1584*f6dc9357SAndroid Build Coastguard Worker {
1585*f6dc9357SAndroid Build Coastguard Worker char s[16];
1586*f6dc9357SAndroid Build Coastguard Worker ConvertUInt32ToString(v, s);
1587*f6dc9357SAndroid Build Coastguard Worker f.AddString(s);
1588*f6dc9357SAndroid Build Coastguard Worker }
1589*f6dc9357SAndroid Build Coastguard Worker
1590*f6dc9357SAndroid Build Coastguard Worker static inline void PrintUInt32(UString &dest, UInt32 v)
1591*f6dc9357SAndroid Build Coastguard Worker {
1592*f6dc9357SAndroid Build Coastguard Worker dest.Add_UInt32(v);
1593*f6dc9357SAndroid Build Coastguard Worker }
1594*f6dc9357SAndroid Build Coastguard Worker
1595*f6dc9357SAndroid Build Coastguard Worker static void PrintHex(CTextFile &f, UInt32 val)
1596*f6dc9357SAndroid Build Coastguard Worker {
1597*f6dc9357SAndroid Build Coastguard Worker char temp[16];
1598*f6dc9357SAndroid Build Coastguard Worker temp[0] = '0';
1599*f6dc9357SAndroid Build Coastguard Worker temp[1] = 'x';
1600*f6dc9357SAndroid Build Coastguard Worker ConvertUInt32ToHex(val, temp + 2);
1601*f6dc9357SAndroid Build Coastguard Worker f.AddString(temp);
1602*f6dc9357SAndroid Build Coastguard Worker }
1603*f6dc9357SAndroid Build Coastguard Worker
1604*f6dc9357SAndroid Build Coastguard Worker static void PrintVersion(CTextFile &f, UInt32 ms, UInt32 ls)
1605*f6dc9357SAndroid Build Coastguard Worker {
1606*f6dc9357SAndroid Build Coastguard Worker PrintUInt32(f, HIWORD(ms)); f.AddChar(',');
1607*f6dc9357SAndroid Build Coastguard Worker PrintUInt32(f, LOWORD(ms)); f.AddChar(',');
1608*f6dc9357SAndroid Build Coastguard Worker PrintUInt32(f, HIWORD(ls)); f.AddChar(',');
1609*f6dc9357SAndroid Build Coastguard Worker PrintUInt32(f, LOWORD(ls));
1610*f6dc9357SAndroid Build Coastguard Worker }
1611*f6dc9357SAndroid Build Coastguard Worker
1612*f6dc9357SAndroid Build Coastguard Worker static void PrintVersion(UString &s, UInt32 ms, UInt32 ls)
1613*f6dc9357SAndroid Build Coastguard Worker {
1614*f6dc9357SAndroid Build Coastguard Worker PrintUInt32(s, HIWORD(ms)); s.Add_Dot();
1615*f6dc9357SAndroid Build Coastguard Worker PrintUInt32(s, LOWORD(ms)); s.Add_Dot();
1616*f6dc9357SAndroid Build Coastguard Worker PrintUInt32(s, HIWORD(ls)); s.Add_Dot();
1617*f6dc9357SAndroid Build Coastguard Worker PrintUInt32(s, LOWORD(ls));
1618*f6dc9357SAndroid Build Coastguard Worker }
1619*f6dc9357SAndroid Build Coastguard Worker
1620*f6dc9357SAndroid Build Coastguard Worker static const char * const k_VS_FileFlags[] =
1621*f6dc9357SAndroid Build Coastguard Worker {
1622*f6dc9357SAndroid Build Coastguard Worker "DEBUG"
1623*f6dc9357SAndroid Build Coastguard Worker , "PRERELEASE"
1624*f6dc9357SAndroid Build Coastguard Worker , "PATCHED"
1625*f6dc9357SAndroid Build Coastguard Worker , "PRIVATEBUILD"
1626*f6dc9357SAndroid Build Coastguard Worker , "INFOINFERRED"
1627*f6dc9357SAndroid Build Coastguard Worker , "SPECIALBUILD"
1628*f6dc9357SAndroid Build Coastguard Worker };
1629*f6dc9357SAndroid Build Coastguard Worker
1630*f6dc9357SAndroid Build Coastguard Worker static const CUInt32PCharPair k_VS_FileOS[] =
1631*f6dc9357SAndroid Build Coastguard Worker {
1632*f6dc9357SAndroid Build Coastguard Worker { 0x10001, "VOS_DOS_WINDOWS16" },
1633*f6dc9357SAndroid Build Coastguard Worker { 0x10004, "VOS_DOS_WINDOWS32" },
1634*f6dc9357SAndroid Build Coastguard Worker { 0x20002, "VOS_OS216_PM16" },
1635*f6dc9357SAndroid Build Coastguard Worker { 0x30003, "VOS_OS232_PM32" },
1636*f6dc9357SAndroid Build Coastguard Worker { 0x40004, "VOS_NT_WINDOWS32" }
1637*f6dc9357SAndroid Build Coastguard Worker };
1638*f6dc9357SAndroid Build Coastguard Worker
1639*f6dc9357SAndroid Build Coastguard Worker static const char * const k_VS_FileOS_High[] =
1640*f6dc9357SAndroid Build Coastguard Worker {
1641*f6dc9357SAndroid Build Coastguard Worker "VOS_UNKNOWN"
1642*f6dc9357SAndroid Build Coastguard Worker , "VOS_DOS"
1643*f6dc9357SAndroid Build Coastguard Worker , "VOS_OS216"
1644*f6dc9357SAndroid Build Coastguard Worker , "VOS_OS232"
1645*f6dc9357SAndroid Build Coastguard Worker , "VOS_NT"
1646*f6dc9357SAndroid Build Coastguard Worker , "VOS_WINCE"
1647*f6dc9357SAndroid Build Coastguard Worker };
1648*f6dc9357SAndroid Build Coastguard Worker
1649*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kMY_VFT_DRV = 3;
1650*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kMY_VFT_FONT = 4;
1651*f6dc9357SAndroid Build Coastguard Worker
1652*f6dc9357SAndroid Build Coastguard Worker static const char * const k_VS_FileOS_Low[] =
1653*f6dc9357SAndroid Build Coastguard Worker {
1654*f6dc9357SAndroid Build Coastguard Worker "VOS__BASE"
1655*f6dc9357SAndroid Build Coastguard Worker , "VOS__WINDOWS16"
1656*f6dc9357SAndroid Build Coastguard Worker , "VOS__PM16"
1657*f6dc9357SAndroid Build Coastguard Worker , "VOS__PM32"
1658*f6dc9357SAndroid Build Coastguard Worker , "VOS__WINDOWS32"
1659*f6dc9357SAndroid Build Coastguard Worker };
1660*f6dc9357SAndroid Build Coastguard Worker
1661*f6dc9357SAndroid Build Coastguard Worker static const char * const k_VS_FileType[] =
1662*f6dc9357SAndroid Build Coastguard Worker {
1663*f6dc9357SAndroid Build Coastguard Worker "VFT_UNKNOWN"
1664*f6dc9357SAndroid Build Coastguard Worker , "VFT_APP"
1665*f6dc9357SAndroid Build Coastguard Worker , "VFT_DLL"
1666*f6dc9357SAndroid Build Coastguard Worker , "VFT_DRV"
1667*f6dc9357SAndroid Build Coastguard Worker , "VFT_FONT"
1668*f6dc9357SAndroid Build Coastguard Worker , "VFT_VXD"
1669*f6dc9357SAndroid Build Coastguard Worker , "0x6"
1670*f6dc9357SAndroid Build Coastguard Worker , "VFT_STATIC_LIB"
1671*f6dc9357SAndroid Build Coastguard Worker };
1672*f6dc9357SAndroid Build Coastguard Worker
1673*f6dc9357SAndroid Build Coastguard Worker // Subtype for VFT_DRV Type
1674*f6dc9357SAndroid Build Coastguard Worker static const char * const k_VS_FileSubType_DRV[] =
1675*f6dc9357SAndroid Build Coastguard Worker {
1676*f6dc9357SAndroid Build Coastguard Worker "0"
1677*f6dc9357SAndroid Build Coastguard Worker , "PRINTER"
1678*f6dc9357SAndroid Build Coastguard Worker , "KEYBOARD"
1679*f6dc9357SAndroid Build Coastguard Worker , "LANGUAGE"
1680*f6dc9357SAndroid Build Coastguard Worker , "DISPLAY"
1681*f6dc9357SAndroid Build Coastguard Worker , "MOUSE"
1682*f6dc9357SAndroid Build Coastguard Worker , "NETWORK"
1683*f6dc9357SAndroid Build Coastguard Worker , "SYSTEM"
1684*f6dc9357SAndroid Build Coastguard Worker , "INSTALLABLE"
1685*f6dc9357SAndroid Build Coastguard Worker , "SOUND"
1686*f6dc9357SAndroid Build Coastguard Worker , "COMM"
1687*f6dc9357SAndroid Build Coastguard Worker , "INPUTMETHOD"
1688*f6dc9357SAndroid Build Coastguard Worker , "VERSIONED_PRINTER"
1689*f6dc9357SAndroid Build Coastguard Worker };
1690*f6dc9357SAndroid Build Coastguard Worker
1691*f6dc9357SAndroid Build Coastguard Worker // Subtype for VFT_FONT Type
1692*f6dc9357SAndroid Build Coastguard Worker static const char * const k_VS_FileSubType_FONT[] =
1693*f6dc9357SAndroid Build Coastguard Worker {
1694*f6dc9357SAndroid Build Coastguard Worker "0"
1695*f6dc9357SAndroid Build Coastguard Worker , "VFT2_FONT_RASTER"
1696*f6dc9357SAndroid Build Coastguard Worker , "VFT2_FONT_VECTOR"
1697*f6dc9357SAndroid Build Coastguard Worker , "VFT2_FONT_TRUETYPE"
1698*f6dc9357SAndroid Build Coastguard Worker };
1699*f6dc9357SAndroid Build Coastguard Worker
1700*f6dc9357SAndroid Build Coastguard Worker static int FindKey(CObjectVector<CStringKeyValue> &v, const char *key)
1701*f6dc9357SAndroid Build Coastguard Worker {
1702*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (i, v)
1703*f6dc9357SAndroid Build Coastguard Worker if (v[i].Key.IsEqualTo(key))
1704*f6dc9357SAndroid Build Coastguard Worker return (int)i;
1705*f6dc9357SAndroid Build Coastguard Worker return -1;
1706*f6dc9357SAndroid Build Coastguard Worker }
1707*f6dc9357SAndroid Build Coastguard Worker
1708*f6dc9357SAndroid Build Coastguard Worker static void AddToUniqueUStringVector(CObjectVector<CStringKeyValue> &v, const UString &key, const UString &value)
1709*f6dc9357SAndroid Build Coastguard Worker {
1710*f6dc9357SAndroid Build Coastguard Worker bool needInsert = false;
1711*f6dc9357SAndroid Build Coastguard Worker unsigned i;
1712*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < v.Size(); i++)
1713*f6dc9357SAndroid Build Coastguard Worker {
1714*f6dc9357SAndroid Build Coastguard Worker if (v[i].Key == key)
1715*f6dc9357SAndroid Build Coastguard Worker {
1716*f6dc9357SAndroid Build Coastguard Worker if (v[i].Value == value)
1717*f6dc9357SAndroid Build Coastguard Worker return;
1718*f6dc9357SAndroid Build Coastguard Worker needInsert = true;
1719*f6dc9357SAndroid Build Coastguard Worker }
1720*f6dc9357SAndroid Build Coastguard Worker else if (needInsert)
1721*f6dc9357SAndroid Build Coastguard Worker break;
1722*f6dc9357SAndroid Build Coastguard Worker }
1723*f6dc9357SAndroid Build Coastguard Worker CStringKeyValue &pair = v.InsertNew(i);
1724*f6dc9357SAndroid Build Coastguard Worker pair.Key = key;
1725*f6dc9357SAndroid Build Coastguard Worker pair.Value = value;
1726*f6dc9357SAndroid Build Coastguard Worker }
1727*f6dc9357SAndroid Build Coastguard Worker
1728*f6dc9357SAndroid Build Coastguard Worker void CMy_VS_FIXEDFILEINFO::PrintToTextFile(CTextFile &f, CObjectVector<CStringKeyValue> &keys)
1729*f6dc9357SAndroid Build Coastguard Worker {
1730*f6dc9357SAndroid Build Coastguard Worker f.AddString("FILEVERSION ");
1731*f6dc9357SAndroid Build Coastguard Worker PrintVersion(f, VersionMS, VersionLS);
1732*f6dc9357SAndroid Build Coastguard Worker f.NewLine();
1733*f6dc9357SAndroid Build Coastguard Worker
1734*f6dc9357SAndroid Build Coastguard Worker f.AddString("PRODUCTVERSION ");
1735*f6dc9357SAndroid Build Coastguard Worker PrintVersion(f, ProductVersionMS, ProductVersionLS);
1736*f6dc9357SAndroid Build Coastguard Worker f.NewLine();
1737*f6dc9357SAndroid Build Coastguard Worker
1738*f6dc9357SAndroid Build Coastguard Worker {
1739*f6dc9357SAndroid Build Coastguard Worker UString s;
1740*f6dc9357SAndroid Build Coastguard Worker PrintVersion(s, VersionMS, VersionLS);
1741*f6dc9357SAndroid Build Coastguard Worker AddToUniqueUStringVector(keys, L"FileVersion", s);
1742*f6dc9357SAndroid Build Coastguard Worker }
1743*f6dc9357SAndroid Build Coastguard Worker {
1744*f6dc9357SAndroid Build Coastguard Worker UString s;
1745*f6dc9357SAndroid Build Coastguard Worker PrintVersion(s, ProductVersionMS, ProductVersionLS);
1746*f6dc9357SAndroid Build Coastguard Worker AddToUniqueUStringVector(keys, L"ProductVersion", s);
1747*f6dc9357SAndroid Build Coastguard Worker }
1748*f6dc9357SAndroid Build Coastguard Worker
1749*f6dc9357SAndroid Build Coastguard Worker f.AddString("FILEFLAGSMASK ");
1750*f6dc9357SAndroid Build Coastguard Worker PrintHex(f, FlagsMask);
1751*f6dc9357SAndroid Build Coastguard Worker f.NewLine();
1752*f6dc9357SAndroid Build Coastguard Worker
1753*f6dc9357SAndroid Build Coastguard Worker f.AddString("FILEFLAGS ");
1754*f6dc9357SAndroid Build Coastguard Worker {
1755*f6dc9357SAndroid Build Coastguard Worker bool wasPrinted = false;
1756*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < Z7_ARRAY_SIZE(k_VS_FileFlags); i++)
1757*f6dc9357SAndroid Build Coastguard Worker {
1758*f6dc9357SAndroid Build Coastguard Worker if ((Flags & ((UInt32)1 << i)) != 0)
1759*f6dc9357SAndroid Build Coastguard Worker {
1760*f6dc9357SAndroid Build Coastguard Worker if (wasPrinted)
1761*f6dc9357SAndroid Build Coastguard Worker f.AddString(" | ");
1762*f6dc9357SAndroid Build Coastguard Worker f.AddString("VS_FF_");
1763*f6dc9357SAndroid Build Coastguard Worker f.AddString(k_VS_FileFlags[i]);
1764*f6dc9357SAndroid Build Coastguard Worker wasPrinted = true;
1765*f6dc9357SAndroid Build Coastguard Worker }
1766*f6dc9357SAndroid Build Coastguard Worker }
1767*f6dc9357SAndroid Build Coastguard Worker UInt32 v = Flags & ~(((UInt32)1 << Z7_ARRAY_SIZE(k_VS_FileFlags)) - 1);
1768*f6dc9357SAndroid Build Coastguard Worker if (v != 0 || !wasPrinted)
1769*f6dc9357SAndroid Build Coastguard Worker {
1770*f6dc9357SAndroid Build Coastguard Worker if (wasPrinted)
1771*f6dc9357SAndroid Build Coastguard Worker f.AddString(" | ");
1772*f6dc9357SAndroid Build Coastguard Worker PrintHex(f, v);
1773*f6dc9357SAndroid Build Coastguard Worker }
1774*f6dc9357SAndroid Build Coastguard Worker }
1775*f6dc9357SAndroid Build Coastguard Worker f.NewLine();
1776*f6dc9357SAndroid Build Coastguard Worker
1777*f6dc9357SAndroid Build Coastguard Worker // OS = 0x111230;
1778*f6dc9357SAndroid Build Coastguard Worker f.AddString("FILEOS ");
1779*f6dc9357SAndroid Build Coastguard Worker unsigned i;
1780*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < Z7_ARRAY_SIZE(k_VS_FileOS); i++)
1781*f6dc9357SAndroid Build Coastguard Worker {
1782*f6dc9357SAndroid Build Coastguard Worker const CUInt32PCharPair &pair = k_VS_FileOS[i];
1783*f6dc9357SAndroid Build Coastguard Worker if (OS == pair.Value)
1784*f6dc9357SAndroid Build Coastguard Worker {
1785*f6dc9357SAndroid Build Coastguard Worker // continue;
1786*f6dc9357SAndroid Build Coastguard Worker // f.AddString("VOS_");
1787*f6dc9357SAndroid Build Coastguard Worker f.AddString(pair.Name);
1788*f6dc9357SAndroid Build Coastguard Worker break;
1789*f6dc9357SAndroid Build Coastguard Worker }
1790*f6dc9357SAndroid Build Coastguard Worker }
1791*f6dc9357SAndroid Build Coastguard Worker if (i == Z7_ARRAY_SIZE(k_VS_FileOS))
1792*f6dc9357SAndroid Build Coastguard Worker {
1793*f6dc9357SAndroid Build Coastguard Worker UInt32 high = OS >> 16;
1794*f6dc9357SAndroid Build Coastguard Worker if (high < Z7_ARRAY_SIZE(k_VS_FileOS_High))
1795*f6dc9357SAndroid Build Coastguard Worker f.AddString(k_VS_FileOS_High[high]);
1796*f6dc9357SAndroid Build Coastguard Worker else
1797*f6dc9357SAndroid Build Coastguard Worker PrintHex(f, high << 16);
1798*f6dc9357SAndroid Build Coastguard Worker UInt32 low = OS & 0xFFFF;
1799*f6dc9357SAndroid Build Coastguard Worker if (low != 0)
1800*f6dc9357SAndroid Build Coastguard Worker {
1801*f6dc9357SAndroid Build Coastguard Worker f.AddString(" | ");
1802*f6dc9357SAndroid Build Coastguard Worker if (low < Z7_ARRAY_SIZE(k_VS_FileOS_Low))
1803*f6dc9357SAndroid Build Coastguard Worker f.AddString(k_VS_FileOS_Low[low]);
1804*f6dc9357SAndroid Build Coastguard Worker else
1805*f6dc9357SAndroid Build Coastguard Worker PrintHex(f, low);
1806*f6dc9357SAndroid Build Coastguard Worker }
1807*f6dc9357SAndroid Build Coastguard Worker }
1808*f6dc9357SAndroid Build Coastguard Worker f.NewLine();
1809*f6dc9357SAndroid Build Coastguard Worker
1810*f6dc9357SAndroid Build Coastguard Worker f.AddString("FILETYPE ");
1811*f6dc9357SAndroid Build Coastguard Worker if (Type < Z7_ARRAY_SIZE(k_VS_FileType))
1812*f6dc9357SAndroid Build Coastguard Worker f.AddString(k_VS_FileType[Type]);
1813*f6dc9357SAndroid Build Coastguard Worker else
1814*f6dc9357SAndroid Build Coastguard Worker PrintHex(f, Type);
1815*f6dc9357SAndroid Build Coastguard Worker f.NewLine();
1816*f6dc9357SAndroid Build Coastguard Worker
1817*f6dc9357SAndroid Build Coastguard Worker f.AddString("FILESUBTYPE ");
1818*f6dc9357SAndroid Build Coastguard Worker bool needPrintSubType = true;
1819*f6dc9357SAndroid Build Coastguard Worker if (Type == kMY_VFT_DRV)
1820*f6dc9357SAndroid Build Coastguard Worker {
1821*f6dc9357SAndroid Build Coastguard Worker if (Subtype != 0 && Subtype < Z7_ARRAY_SIZE(k_VS_FileSubType_DRV))
1822*f6dc9357SAndroid Build Coastguard Worker {
1823*f6dc9357SAndroid Build Coastguard Worker f.AddString("VFT2_DRV_");
1824*f6dc9357SAndroid Build Coastguard Worker f.AddString(k_VS_FileSubType_DRV[Subtype]);
1825*f6dc9357SAndroid Build Coastguard Worker needPrintSubType = false;
1826*f6dc9357SAndroid Build Coastguard Worker }
1827*f6dc9357SAndroid Build Coastguard Worker }
1828*f6dc9357SAndroid Build Coastguard Worker else if (Type == kMY_VFT_FONT)
1829*f6dc9357SAndroid Build Coastguard Worker {
1830*f6dc9357SAndroid Build Coastguard Worker if (Subtype != 0 && Subtype < Z7_ARRAY_SIZE(k_VS_FileSubType_FONT))
1831*f6dc9357SAndroid Build Coastguard Worker {
1832*f6dc9357SAndroid Build Coastguard Worker f.AddString(k_VS_FileSubType_FONT[Subtype]);
1833*f6dc9357SAndroid Build Coastguard Worker needPrintSubType = false;
1834*f6dc9357SAndroid Build Coastguard Worker }
1835*f6dc9357SAndroid Build Coastguard Worker }
1836*f6dc9357SAndroid Build Coastguard Worker if (needPrintSubType)
1837*f6dc9357SAndroid Build Coastguard Worker PrintHex(f, Subtype);
1838*f6dc9357SAndroid Build Coastguard Worker f.NewLine();
1839*f6dc9357SAndroid Build Coastguard Worker }
1840*f6dc9357SAndroid Build Coastguard Worker
1841*f6dc9357SAndroid Build Coastguard Worker static void CopyToUString(const Byte *p, UString &s)
1842*f6dc9357SAndroid Build Coastguard Worker {
1843*f6dc9357SAndroid Build Coastguard Worker for (;;)
1844*f6dc9357SAndroid Build Coastguard Worker {
1845*f6dc9357SAndroid Build Coastguard Worker const wchar_t c = (wchar_t)Get16(p);
1846*f6dc9357SAndroid Build Coastguard Worker p += 2;
1847*f6dc9357SAndroid Build Coastguard Worker if (c == 0)
1848*f6dc9357SAndroid Build Coastguard Worker return;
1849*f6dc9357SAndroid Build Coastguard Worker s += c;
1850*f6dc9357SAndroid Build Coastguard Worker }
1851*f6dc9357SAndroid Build Coastguard Worker }
1852*f6dc9357SAndroid Build Coastguard Worker
1853*f6dc9357SAndroid Build Coastguard Worker static void CopyToUString_ByLen16(const Byte *p, unsigned numChars16, UString &s)
1854*f6dc9357SAndroid Build Coastguard Worker {
1855*f6dc9357SAndroid Build Coastguard Worker for (; numChars16; numChars16--)
1856*f6dc9357SAndroid Build Coastguard Worker {
1857*f6dc9357SAndroid Build Coastguard Worker const wchar_t c = (wchar_t)Get16(p);
1858*f6dc9357SAndroid Build Coastguard Worker p += 2;
1859*f6dc9357SAndroid Build Coastguard Worker s += c;
1860*f6dc9357SAndroid Build Coastguard Worker }
1861*f6dc9357SAndroid Build Coastguard Worker }
1862*f6dc9357SAndroid Build Coastguard Worker
1863*f6dc9357SAndroid Build Coastguard Worker static bool CompareWStrStrings(const Byte *p, const char *s)
1864*f6dc9357SAndroid Build Coastguard Worker {
1865*f6dc9357SAndroid Build Coastguard Worker unsigned pos = 0;
1866*f6dc9357SAndroid Build Coastguard Worker for (;;)
1867*f6dc9357SAndroid Build Coastguard Worker {
1868*f6dc9357SAndroid Build Coastguard Worker const Byte c = (Byte)*s++;
1869*f6dc9357SAndroid Build Coastguard Worker if (Get16(p + pos) != c)
1870*f6dc9357SAndroid Build Coastguard Worker return false;
1871*f6dc9357SAndroid Build Coastguard Worker pos += 2;
1872*f6dc9357SAndroid Build Coastguard Worker if (c == 0)
1873*f6dc9357SAndroid Build Coastguard Worker return true;
1874*f6dc9357SAndroid Build Coastguard Worker }
1875*f6dc9357SAndroid Build Coastguard Worker }
1876*f6dc9357SAndroid Build Coastguard Worker
1877*f6dc9357SAndroid Build Coastguard Worker struct CVersionBlock
1878*f6dc9357SAndroid Build Coastguard Worker {
1879*f6dc9357SAndroid Build Coastguard Worker UInt32 TotalLen;
1880*f6dc9357SAndroid Build Coastguard Worker UInt32 ValueLen;
1881*f6dc9357SAndroid Build Coastguard Worker unsigned IsTextValue;
1882*f6dc9357SAndroid Build Coastguard Worker unsigned StrSize;
1883*f6dc9357SAndroid Build Coastguard Worker
1884*f6dc9357SAndroid Build Coastguard Worker bool Parse(const Byte *p, UInt32 size);
1885*f6dc9357SAndroid Build Coastguard Worker };
1886*f6dc9357SAndroid Build Coastguard Worker
1887*f6dc9357SAndroid Build Coastguard Worker static int Get_Utf16Str_Len_InBytes(const Byte *p, size_t size)
1888*f6dc9357SAndroid Build Coastguard Worker {
1889*f6dc9357SAndroid Build Coastguard Worker unsigned pos = 0;
1890*f6dc9357SAndroid Build Coastguard Worker for (;;)
1891*f6dc9357SAndroid Build Coastguard Worker {
1892*f6dc9357SAndroid Build Coastguard Worker if (pos + 1 >= size)
1893*f6dc9357SAndroid Build Coastguard Worker return -1;
1894*f6dc9357SAndroid Build Coastguard Worker if (Get16(p + pos) == 0)
1895*f6dc9357SAndroid Build Coastguard Worker return (int)pos;
1896*f6dc9357SAndroid Build Coastguard Worker pos += 2;
1897*f6dc9357SAndroid Build Coastguard Worker }
1898*f6dc9357SAndroid Build Coastguard Worker }
1899*f6dc9357SAndroid Build Coastguard Worker
1900*f6dc9357SAndroid Build Coastguard Worker static int Get_Utf16Str_Len_InBytes_AllowNonZeroTail(const Byte *p, size_t size)
1901*f6dc9357SAndroid Build Coastguard Worker {
1902*f6dc9357SAndroid Build Coastguard Worker unsigned pos = 0;
1903*f6dc9357SAndroid Build Coastguard Worker for (;;)
1904*f6dc9357SAndroid Build Coastguard Worker {
1905*f6dc9357SAndroid Build Coastguard Worker if (pos + 1 >= size)
1906*f6dc9357SAndroid Build Coastguard Worker {
1907*f6dc9357SAndroid Build Coastguard Worker if (pos == size)
1908*f6dc9357SAndroid Build Coastguard Worker return (int)pos;
1909*f6dc9357SAndroid Build Coastguard Worker return -1;
1910*f6dc9357SAndroid Build Coastguard Worker }
1911*f6dc9357SAndroid Build Coastguard Worker if (Get16(p + pos) == 0)
1912*f6dc9357SAndroid Build Coastguard Worker return (int)pos;
1913*f6dc9357SAndroid Build Coastguard Worker pos += 2;
1914*f6dc9357SAndroid Build Coastguard Worker }
1915*f6dc9357SAndroid Build Coastguard Worker }
1916*f6dc9357SAndroid Build Coastguard Worker
1917*f6dc9357SAndroid Build Coastguard Worker static const unsigned k_ResoureBlockHeader_Size = 6;
1918*f6dc9357SAndroid Build Coastguard Worker
1919*f6dc9357SAndroid Build Coastguard Worker bool CVersionBlock::Parse(const Byte *p, UInt32 size)
1920*f6dc9357SAndroid Build Coastguard Worker {
1921*f6dc9357SAndroid Build Coastguard Worker if (size < k_ResoureBlockHeader_Size)
1922*f6dc9357SAndroid Build Coastguard Worker return false;
1923*f6dc9357SAndroid Build Coastguard Worker TotalLen = Get16(p);
1924*f6dc9357SAndroid Build Coastguard Worker ValueLen = Get16(p + 2);
1925*f6dc9357SAndroid Build Coastguard Worker if (TotalLen < k_ResoureBlockHeader_Size || TotalLen > size)
1926*f6dc9357SAndroid Build Coastguard Worker return false;
1927*f6dc9357SAndroid Build Coastguard Worker IsTextValue = Get16(p + 4);
1928*f6dc9357SAndroid Build Coastguard Worker if (IsTextValue > 1)
1929*f6dc9357SAndroid Build Coastguard Worker return false;
1930*f6dc9357SAndroid Build Coastguard Worker StrSize = 0;
1931*f6dc9357SAndroid Build Coastguard Worker const int t = Get_Utf16Str_Len_InBytes(p + k_ResoureBlockHeader_Size,
1932*f6dc9357SAndroid Build Coastguard Worker TotalLen - k_ResoureBlockHeader_Size);
1933*f6dc9357SAndroid Build Coastguard Worker if (t < 0)
1934*f6dc9357SAndroid Build Coastguard Worker return false;
1935*f6dc9357SAndroid Build Coastguard Worker StrSize = (unsigned)t;
1936*f6dc9357SAndroid Build Coastguard Worker return true;
1937*f6dc9357SAndroid Build Coastguard Worker }
1938*f6dc9357SAndroid Build Coastguard Worker
1939*f6dc9357SAndroid Build Coastguard Worker static void AddParamString(CTextFile &f, const Byte *p, size_t sLen)
1940*f6dc9357SAndroid Build Coastguard Worker {
1941*f6dc9357SAndroid Build Coastguard Worker f.AddChar(' ');
1942*f6dc9357SAndroid Build Coastguard Worker f.AddChar('\"');
1943*f6dc9357SAndroid Build Coastguard Worker f.AddBytes(p, sLen);
1944*f6dc9357SAndroid Build Coastguard Worker f.AddChar('\"');
1945*f6dc9357SAndroid Build Coastguard Worker }
1946*f6dc9357SAndroid Build Coastguard Worker
1947*f6dc9357SAndroid Build Coastguard Worker static bool ParseVersion(const Byte *p, UInt32 size, CTextFile &f, CObjectVector<CStringKeyValue> &keys)
1948*f6dc9357SAndroid Build Coastguard Worker {
1949*f6dc9357SAndroid Build Coastguard Worker UInt32 pos;
1950*f6dc9357SAndroid Build Coastguard Worker {
1951*f6dc9357SAndroid Build Coastguard Worker const unsigned k_sizeof_VS_FIXEDFILEINFO = 13 * 4;
1952*f6dc9357SAndroid Build Coastguard Worker
1953*f6dc9357SAndroid Build Coastguard Worker CVersionBlock vb;
1954*f6dc9357SAndroid Build Coastguard Worker if (!vb.Parse(p, size))
1955*f6dc9357SAndroid Build Coastguard Worker return false;
1956*f6dc9357SAndroid Build Coastguard Worker if (vb.ValueLen != k_sizeof_VS_FIXEDFILEINFO) // maybe 0 is allowed here?
1957*f6dc9357SAndroid Build Coastguard Worker return false;
1958*f6dc9357SAndroid Build Coastguard Worker if (vb.IsTextValue)
1959*f6dc9357SAndroid Build Coastguard Worker return false;
1960*f6dc9357SAndroid Build Coastguard Worker pos = k_ResoureBlockHeader_Size;
1961*f6dc9357SAndroid Build Coastguard Worker if (!CompareWStrStrings(p + pos, "VS_VERSION_INFO"))
1962*f6dc9357SAndroid Build Coastguard Worker return false;
1963*f6dc9357SAndroid Build Coastguard Worker pos += vb.StrSize + 2;
1964*f6dc9357SAndroid Build Coastguard Worker pos += (4 - pos) & 3;
1965*f6dc9357SAndroid Build Coastguard Worker if (pos + vb.ValueLen > vb.TotalLen)
1966*f6dc9357SAndroid Build Coastguard Worker return false;
1967*f6dc9357SAndroid Build Coastguard Worker /* sometimes resource contains zeros in remainder.
1968*f6dc9357SAndroid Build Coastguard Worker So we don't check that size != vb.TotalLen
1969*f6dc9357SAndroid Build Coastguard Worker // if (size != vb.TotalLen) return false;
1970*f6dc9357SAndroid Build Coastguard Worker */
1971*f6dc9357SAndroid Build Coastguard Worker if (size > vb.TotalLen)
1972*f6dc9357SAndroid Build Coastguard Worker size = vb.TotalLen;
1973*f6dc9357SAndroid Build Coastguard Worker CMy_VS_FIXEDFILEINFO FixedFileInfo;
1974*f6dc9357SAndroid Build Coastguard Worker if (!FixedFileInfo.Parse(p + pos))
1975*f6dc9357SAndroid Build Coastguard Worker return false;
1976*f6dc9357SAndroid Build Coastguard Worker FixedFileInfo.PrintToTextFile(f, keys);
1977*f6dc9357SAndroid Build Coastguard Worker pos += vb.ValueLen;
1978*f6dc9357SAndroid Build Coastguard Worker }
1979*f6dc9357SAndroid Build Coastguard Worker
1980*f6dc9357SAndroid Build Coastguard Worker f.OpenBlock(0);
1981*f6dc9357SAndroid Build Coastguard Worker
1982*f6dc9357SAndroid Build Coastguard Worker for (;;)
1983*f6dc9357SAndroid Build Coastguard Worker {
1984*f6dc9357SAndroid Build Coastguard Worker pos += (4 - pos) & 3;
1985*f6dc9357SAndroid Build Coastguard Worker if (pos >= size)
1986*f6dc9357SAndroid Build Coastguard Worker break;
1987*f6dc9357SAndroid Build Coastguard Worker
1988*f6dc9357SAndroid Build Coastguard Worker CVersionBlock vb;
1989*f6dc9357SAndroid Build Coastguard Worker if (!vb.Parse(p + pos, size - pos))
1990*f6dc9357SAndroid Build Coastguard Worker return false;
1991*f6dc9357SAndroid Build Coastguard Worker if (vb.ValueLen != 0)
1992*f6dc9357SAndroid Build Coastguard Worker return false;
1993*f6dc9357SAndroid Build Coastguard Worker const UInt32 endPos = pos + vb.TotalLen;
1994*f6dc9357SAndroid Build Coastguard Worker pos += k_ResoureBlockHeader_Size;
1995*f6dc9357SAndroid Build Coastguard Worker
1996*f6dc9357SAndroid Build Coastguard Worker f.AddSpaces(2);
1997*f6dc9357SAndroid Build Coastguard Worker f.AddString("BLOCK");
1998*f6dc9357SAndroid Build Coastguard Worker AddParamString(f, p + pos, vb.StrSize);
1999*f6dc9357SAndroid Build Coastguard Worker
2000*f6dc9357SAndroid Build Coastguard Worker f.NewLine();
2001*f6dc9357SAndroid Build Coastguard Worker f.OpenBlock(2);
2002*f6dc9357SAndroid Build Coastguard Worker
2003*f6dc9357SAndroid Build Coastguard Worker if (CompareWStrStrings(p + pos, "VarFileInfo"))
2004*f6dc9357SAndroid Build Coastguard Worker {
2005*f6dc9357SAndroid Build Coastguard Worker pos += vb.StrSize + 2;
2006*f6dc9357SAndroid Build Coastguard Worker for (;;)
2007*f6dc9357SAndroid Build Coastguard Worker {
2008*f6dc9357SAndroid Build Coastguard Worker pos += (4 - pos) & 3;
2009*f6dc9357SAndroid Build Coastguard Worker if (pos >= endPos)
2010*f6dc9357SAndroid Build Coastguard Worker break;
2011*f6dc9357SAndroid Build Coastguard Worker CVersionBlock vb2;
2012*f6dc9357SAndroid Build Coastguard Worker if (!vb2.Parse(p + pos, endPos - pos))
2013*f6dc9357SAndroid Build Coastguard Worker return false;
2014*f6dc9357SAndroid Build Coastguard Worker const UInt32 endPos2 = pos + vb2.TotalLen;
2015*f6dc9357SAndroid Build Coastguard Worker if (vb2.IsTextValue)
2016*f6dc9357SAndroid Build Coastguard Worker return false;
2017*f6dc9357SAndroid Build Coastguard Worker pos += k_ResoureBlockHeader_Size;
2018*f6dc9357SAndroid Build Coastguard Worker f.AddSpaces(4);
2019*f6dc9357SAndroid Build Coastguard Worker f.AddString("VALUE");
2020*f6dc9357SAndroid Build Coastguard Worker AddParamString(f, p + pos, vb2.StrSize);
2021*f6dc9357SAndroid Build Coastguard Worker if (!CompareWStrStrings(p + pos, "Translation"))
2022*f6dc9357SAndroid Build Coastguard Worker return false;
2023*f6dc9357SAndroid Build Coastguard Worker pos += vb2.StrSize + 2;
2024*f6dc9357SAndroid Build Coastguard Worker pos += (4 - pos) & 3;
2025*f6dc9357SAndroid Build Coastguard Worker if (pos + vb2.ValueLen != endPos2)
2026*f6dc9357SAndroid Build Coastguard Worker return false;
2027*f6dc9357SAndroid Build Coastguard Worker if ((vb2.ValueLen & 3) != 0)
2028*f6dc9357SAndroid Build Coastguard Worker return false;
2029*f6dc9357SAndroid Build Coastguard Worker UInt32 num = (vb2.ValueLen >> 2);
2030*f6dc9357SAndroid Build Coastguard Worker for (; num != 0; num--, pos += 4)
2031*f6dc9357SAndroid Build Coastguard Worker {
2032*f6dc9357SAndroid Build Coastguard Worker const UInt32 dw = Get32(p + pos);
2033*f6dc9357SAndroid Build Coastguard Worker const UInt32 lang = LOWORD(dw);
2034*f6dc9357SAndroid Build Coastguard Worker const UInt32 codePage = HIWORD(dw);
2035*f6dc9357SAndroid Build Coastguard Worker
2036*f6dc9357SAndroid Build Coastguard Worker f.AddString(", ");
2037*f6dc9357SAndroid Build Coastguard Worker PrintHex(f, lang);
2038*f6dc9357SAndroid Build Coastguard Worker f.AddString(", ");
2039*f6dc9357SAndroid Build Coastguard Worker PrintUInt32(f, codePage);
2040*f6dc9357SAndroid Build Coastguard Worker }
2041*f6dc9357SAndroid Build Coastguard Worker f.NewLine();
2042*f6dc9357SAndroid Build Coastguard Worker }
2043*f6dc9357SAndroid Build Coastguard Worker }
2044*f6dc9357SAndroid Build Coastguard Worker else
2045*f6dc9357SAndroid Build Coastguard Worker {
2046*f6dc9357SAndroid Build Coastguard Worker if (!CompareWStrStrings(p + pos, "StringFileInfo"))
2047*f6dc9357SAndroid Build Coastguard Worker return false;
2048*f6dc9357SAndroid Build Coastguard Worker pos += vb.StrSize + 2;
2049*f6dc9357SAndroid Build Coastguard Worker for (;;)
2050*f6dc9357SAndroid Build Coastguard Worker {
2051*f6dc9357SAndroid Build Coastguard Worker pos += (4 - pos) & 3;
2052*f6dc9357SAndroid Build Coastguard Worker if (pos >= endPos)
2053*f6dc9357SAndroid Build Coastguard Worker break;
2054*f6dc9357SAndroid Build Coastguard Worker CVersionBlock vb2;
2055*f6dc9357SAndroid Build Coastguard Worker if (!vb2.Parse(p + pos, endPos - pos))
2056*f6dc9357SAndroid Build Coastguard Worker return false;
2057*f6dc9357SAndroid Build Coastguard Worker const UInt32 endPos2 = pos + vb2.TotalLen;
2058*f6dc9357SAndroid Build Coastguard Worker if (vb2.ValueLen != 0)
2059*f6dc9357SAndroid Build Coastguard Worker return false;
2060*f6dc9357SAndroid Build Coastguard Worker pos += k_ResoureBlockHeader_Size;
2061*f6dc9357SAndroid Build Coastguard Worker
2062*f6dc9357SAndroid Build Coastguard Worker f.AddSpaces(4);
2063*f6dc9357SAndroid Build Coastguard Worker f.AddString("BLOCK");
2064*f6dc9357SAndroid Build Coastguard Worker AddParamString(f, p + pos, vb2.StrSize);
2065*f6dc9357SAndroid Build Coastguard Worker pos += vb2.StrSize + 2;
2066*f6dc9357SAndroid Build Coastguard Worker
2067*f6dc9357SAndroid Build Coastguard Worker f.NewLine();
2068*f6dc9357SAndroid Build Coastguard Worker f.OpenBlock(4);
2069*f6dc9357SAndroid Build Coastguard Worker
2070*f6dc9357SAndroid Build Coastguard Worker for (;;)
2071*f6dc9357SAndroid Build Coastguard Worker {
2072*f6dc9357SAndroid Build Coastguard Worker pos += (4 - pos) & 3;
2073*f6dc9357SAndroid Build Coastguard Worker if (pos >= endPos2)
2074*f6dc9357SAndroid Build Coastguard Worker break;
2075*f6dc9357SAndroid Build Coastguard Worker
2076*f6dc9357SAndroid Build Coastguard Worker CVersionBlock vb3;
2077*f6dc9357SAndroid Build Coastguard Worker if (!vb3.Parse(p + pos, endPos2 - pos))
2078*f6dc9357SAndroid Build Coastguard Worker return false;
2079*f6dc9357SAndroid Build Coastguard Worker // ValueLen is a number of 16-bit characters (usually it includes zero tail character).
2080*f6dc9357SAndroid Build Coastguard Worker const UInt32 endPos3 = pos + vb3.TotalLen;
2081*f6dc9357SAndroid Build Coastguard Worker pos += k_ResoureBlockHeader_Size;
2082*f6dc9357SAndroid Build Coastguard Worker
2083*f6dc9357SAndroid Build Coastguard Worker // we don't write string if it's not text
2084*f6dc9357SAndroid Build Coastguard Worker if (vb3.IsTextValue)
2085*f6dc9357SAndroid Build Coastguard Worker {
2086*f6dc9357SAndroid Build Coastguard Worker f.AddSpaces(6);
2087*f6dc9357SAndroid Build Coastguard Worker f.AddString("VALUE");
2088*f6dc9357SAndroid Build Coastguard Worker AddParamString(f, p + pos, vb3.StrSize);
2089*f6dc9357SAndroid Build Coastguard Worker UString key;
2090*f6dc9357SAndroid Build Coastguard Worker UString value;
2091*f6dc9357SAndroid Build Coastguard Worker CopyToUString(p + pos, key);
2092*f6dc9357SAndroid Build Coastguard Worker pos += vb3.StrSize + 2;
2093*f6dc9357SAndroid Build Coastguard Worker
2094*f6dc9357SAndroid Build Coastguard Worker pos += (4 - pos) & 3;
2095*f6dc9357SAndroid Build Coastguard Worker if (vb3.ValueLen != 0 && pos /* + 2 */ <= endPos3)
2096*f6dc9357SAndroid Build Coastguard Worker {
2097*f6dc9357SAndroid Build Coastguard Worker f.AddChar(',');
2098*f6dc9357SAndroid Build Coastguard Worker f.AddSpaces((34 - (int)vb3.StrSize) / 2);
2099*f6dc9357SAndroid Build Coastguard Worker // vb3.TotalLen for some PE files (not from msvc) doesn't include tail zero at the end of Value string.
2100*f6dc9357SAndroid Build Coastguard Worker // we allow that minor error.
2101*f6dc9357SAndroid Build Coastguard Worker const int sLen = Get_Utf16Str_Len_InBytes_AllowNonZeroTail(p + pos, endPos3 - pos);
2102*f6dc9357SAndroid Build Coastguard Worker if (sLen < 0)
2103*f6dc9357SAndroid Build Coastguard Worker return false;
2104*f6dc9357SAndroid Build Coastguard Worker /*
2105*f6dc9357SAndroid Build Coastguard Worker if (vb3.ValueLen - 1 != (unsigned)sLen / 2 &&
2106*f6dc9357SAndroid Build Coastguard Worker vb3.ValueLen != (unsigned)sLen / 2)
2107*f6dc9357SAndroid Build Coastguard Worker return false;
2108*f6dc9357SAndroid Build Coastguard Worker */
2109*f6dc9357SAndroid Build Coastguard Worker AddParamString(f, p + pos, (unsigned)sLen);
2110*f6dc9357SAndroid Build Coastguard Worker CopyToUString_ByLen16(p + pos, (unsigned)sLen / 2, value);
2111*f6dc9357SAndroid Build Coastguard Worker // pos += (unsigned)sLen + 2;
2112*f6dc9357SAndroid Build Coastguard Worker }
2113*f6dc9357SAndroid Build Coastguard Worker AddToUniqueUStringVector(keys, key, value);
2114*f6dc9357SAndroid Build Coastguard Worker }
2115*f6dc9357SAndroid Build Coastguard Worker pos = endPos3;
2116*f6dc9357SAndroid Build Coastguard Worker f.NewLine();
2117*f6dc9357SAndroid Build Coastguard Worker }
2118*f6dc9357SAndroid Build Coastguard Worker pos = endPos2;
2119*f6dc9357SAndroid Build Coastguard Worker f.CloseBlock(4);
2120*f6dc9357SAndroid Build Coastguard Worker }
2121*f6dc9357SAndroid Build Coastguard Worker }
2122*f6dc9357SAndroid Build Coastguard Worker f.CloseBlock(2);
2123*f6dc9357SAndroid Build Coastguard Worker pos = endPos;
2124*f6dc9357SAndroid Build Coastguard Worker }
2125*f6dc9357SAndroid Build Coastguard Worker
2126*f6dc9357SAndroid Build Coastguard Worker f.CloseBlock(0);
2127*f6dc9357SAndroid Build Coastguard Worker return true;
2128*f6dc9357SAndroid Build Coastguard Worker }
2129*f6dc9357SAndroid Build Coastguard Worker
2130*f6dc9357SAndroid Build Coastguard Worker
2131*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::OpenResources(unsigned sectionIndex, IInStream *stream, IArchiveOpenCallback *callback)
2132*f6dc9357SAndroid Build Coastguard Worker {
2133*f6dc9357SAndroid Build Coastguard Worker const CSection § = _sections[sectionIndex];
2134*f6dc9357SAndroid Build Coastguard Worker size_t fileSize = sect.PSize;
2135*f6dc9357SAndroid Build Coastguard Worker {
2136*f6dc9357SAndroid Build Coastguard Worker size_t fileSizeMin = sect.PSize;
2137*f6dc9357SAndroid Build Coastguard Worker
2138*f6dc9357SAndroid Build Coastguard Worker if (sect.VSize < sect.PSize)
2139*f6dc9357SAndroid Build Coastguard Worker {
2140*f6dc9357SAndroid Build Coastguard Worker fileSize = fileSizeMin = sect.VSize;
2141*f6dc9357SAndroid Build Coastguard Worker const int numBits = _optHeader.GetNumFileAlignBits();
2142*f6dc9357SAndroid Build Coastguard Worker if (numBits > 0)
2143*f6dc9357SAndroid Build Coastguard Worker {
2144*f6dc9357SAndroid Build Coastguard Worker const UInt32 mask = ((UInt32)1 << numBits) - 1;
2145*f6dc9357SAndroid Build Coastguard Worker const size_t end = (size_t)((sect.VSize + mask) & (UInt32)~mask);
2146*f6dc9357SAndroid Build Coastguard Worker if (end > sect.VSize)
2147*f6dc9357SAndroid Build Coastguard Worker {
2148*f6dc9357SAndroid Build Coastguard Worker if (end <= sect.PSize)
2149*f6dc9357SAndroid Build Coastguard Worker fileSize = end;
2150*f6dc9357SAndroid Build Coastguard Worker else
2151*f6dc9357SAndroid Build Coastguard Worker fileSize = sect.PSize;
2152*f6dc9357SAndroid Build Coastguard Worker }
2153*f6dc9357SAndroid Build Coastguard Worker }
2154*f6dc9357SAndroid Build Coastguard Worker }
2155*f6dc9357SAndroid Build Coastguard Worker
2156*f6dc9357SAndroid Build Coastguard Worker if (fileSize > kFileSizeMax)
2157*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
2158*f6dc9357SAndroid Build Coastguard Worker
2159*f6dc9357SAndroid Build Coastguard Worker {
2160*f6dc9357SAndroid Build Coastguard Worker const UInt64 fileSize64 = fileSize;
2161*f6dc9357SAndroid Build Coastguard Worker if (callback)
2162*f6dc9357SAndroid Build Coastguard Worker RINOK(callback->SetTotal(NULL, &fileSize64))
2163*f6dc9357SAndroid Build Coastguard Worker }
2164*f6dc9357SAndroid Build Coastguard Worker
2165*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekSet(stream, sect.Pa))
2166*f6dc9357SAndroid Build Coastguard Worker
2167*f6dc9357SAndroid Build Coastguard Worker _buf.Alloc(fileSize);
2168*f6dc9357SAndroid Build Coastguard Worker
2169*f6dc9357SAndroid Build Coastguard Worker size_t pos;
2170*f6dc9357SAndroid Build Coastguard Worker
2171*f6dc9357SAndroid Build Coastguard Worker for (pos = 0; pos < fileSize;)
2172*f6dc9357SAndroid Build Coastguard Worker {
2173*f6dc9357SAndroid Build Coastguard Worker {
2174*f6dc9357SAndroid Build Coastguard Worker const UInt64 offset64 = pos;
2175*f6dc9357SAndroid Build Coastguard Worker if (callback)
2176*f6dc9357SAndroid Build Coastguard Worker RINOK(callback->SetCompleted(NULL, &offset64))
2177*f6dc9357SAndroid Build Coastguard Worker }
2178*f6dc9357SAndroid Build Coastguard Worker size_t rem = MyMin(fileSize - pos, (size_t)(1 << 22));
2179*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream(stream, _buf + pos, &rem))
2180*f6dc9357SAndroid Build Coastguard Worker if (rem == 0)
2181*f6dc9357SAndroid Build Coastguard Worker {
2182*f6dc9357SAndroid Build Coastguard Worker if (pos < fileSizeMin)
2183*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
2184*f6dc9357SAndroid Build Coastguard Worker break;
2185*f6dc9357SAndroid Build Coastguard Worker }
2186*f6dc9357SAndroid Build Coastguard Worker pos += rem;
2187*f6dc9357SAndroid Build Coastguard Worker }
2188*f6dc9357SAndroid Build Coastguard Worker
2189*f6dc9357SAndroid Build Coastguard Worker if (pos < fileSize)
2190*f6dc9357SAndroid Build Coastguard Worker memset(_buf + pos, 0, fileSize - pos);
2191*f6dc9357SAndroid Build Coastguard Worker }
2192*f6dc9357SAndroid Build Coastguard Worker
2193*f6dc9357SAndroid Build Coastguard Worker _usedRes.Alloc(fileSize);
2194*f6dc9357SAndroid Build Coastguard Worker CRecordVector<CTableItem> specItems;
2195*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadTable(0, specItems))
2196*f6dc9357SAndroid Build Coastguard Worker
2197*f6dc9357SAndroid Build Coastguard Worker _oneLang = true;
2198*f6dc9357SAndroid Build Coastguard Worker bool stringsOk = true;
2199*f6dc9357SAndroid Build Coastguard Worker size_t maxOffset = 0;
2200*f6dc9357SAndroid Build Coastguard Worker
2201*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (i, specItems)
2202*f6dc9357SAndroid Build Coastguard Worker {
2203*f6dc9357SAndroid Build Coastguard Worker const CTableItem &item1 = specItems[i];
2204*f6dc9357SAndroid Build Coastguard Worker if ((item1.Offset & kFlag) == 0)
2205*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
2206*f6dc9357SAndroid Build Coastguard Worker
2207*f6dc9357SAndroid Build Coastguard Worker CRecordVector<CTableItem> specItems2;
2208*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadTable(item1.Offset & kMask, specItems2))
2209*f6dc9357SAndroid Build Coastguard Worker
2210*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (j, specItems2)
2211*f6dc9357SAndroid Build Coastguard Worker {
2212*f6dc9357SAndroid Build Coastguard Worker const CTableItem &item2 = specItems2[j];
2213*f6dc9357SAndroid Build Coastguard Worker if ((item2.Offset & kFlag) == 0)
2214*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
2215*f6dc9357SAndroid Build Coastguard Worker
2216*f6dc9357SAndroid Build Coastguard Worker CRecordVector<CTableItem> specItems3;
2217*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadTable(item2.Offset & kMask, specItems3))
2218*f6dc9357SAndroid Build Coastguard Worker
2219*f6dc9357SAndroid Build Coastguard Worker CResItem item;
2220*f6dc9357SAndroid Build Coastguard Worker item.Type = item1.ID;
2221*f6dc9357SAndroid Build Coastguard Worker item.ID = item2.ID;
2222*f6dc9357SAndroid Build Coastguard Worker
2223*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (k, specItems3)
2224*f6dc9357SAndroid Build Coastguard Worker {
2225*f6dc9357SAndroid Build Coastguard Worker if (_items.Size() >= kNumResItemsMax)
2226*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
2227*f6dc9357SAndroid Build Coastguard Worker const CTableItem &item3 = specItems3[k];
2228*f6dc9357SAndroid Build Coastguard Worker if ((item3.Offset & kFlag) != 0)
2229*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
2230*f6dc9357SAndroid Build Coastguard Worker if (item3.Offset >= _buf.Size() || _buf.Size() - item3.Offset < 16)
2231*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
2232*f6dc9357SAndroid Build Coastguard Worker const Byte *buf = _buf + item3.Offset;
2233*f6dc9357SAndroid Build Coastguard Worker item.Lang = item3.ID;
2234*f6dc9357SAndroid Build Coastguard Worker item.Offset = Get32(buf + 0);
2235*f6dc9357SAndroid Build Coastguard Worker item.Size = Get32(buf + 4);
2236*f6dc9357SAndroid Build Coastguard Worker // UInt32 codePage = Get32(buf + 8);
2237*f6dc9357SAndroid Build Coastguard Worker if (Get32(buf + 12) != 0)
2238*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
2239*f6dc9357SAndroid Build Coastguard Worker if (!_items.IsEmpty() && _oneLang && !item.IsNameEqual(_items.Back()))
2240*f6dc9357SAndroid Build Coastguard Worker _oneLang = false;
2241*f6dc9357SAndroid Build Coastguard Worker
2242*f6dc9357SAndroid Build Coastguard Worker item.HeaderSize = 0;
2243*f6dc9357SAndroid Build Coastguard Worker
2244*f6dc9357SAndroid Build Coastguard Worker size_t offset = item.Offset - sect.Va;
2245*f6dc9357SAndroid Build Coastguard Worker if (offset > maxOffset)
2246*f6dc9357SAndroid Build Coastguard Worker maxOffset = offset;
2247*f6dc9357SAndroid Build Coastguard Worker if (offset + item.Size > maxOffset)
2248*f6dc9357SAndroid Build Coastguard Worker maxOffset = offset + item.Size;
2249*f6dc9357SAndroid Build Coastguard Worker
2250*f6dc9357SAndroid Build Coastguard Worker if (CheckItem(sect, item, offset))
2251*f6dc9357SAndroid Build Coastguard Worker {
2252*f6dc9357SAndroid Build Coastguard Worker const Byte *data = _buf + offset;
2253*f6dc9357SAndroid Build Coastguard Worker if (item.IsBmp())
2254*f6dc9357SAndroid Build Coastguard Worker item.HeaderSize = SetBitmapHeader(item.Header, data, item.Size);
2255*f6dc9357SAndroid Build Coastguard Worker else if (item.IsIcon())
2256*f6dc9357SAndroid Build Coastguard Worker item.HeaderSize = SetIconHeader(item.Header, data, item.Size);
2257*f6dc9357SAndroid Build Coastguard Worker else if (item.IsString())
2258*f6dc9357SAndroid Build Coastguard Worker {
2259*f6dc9357SAndroid Build Coastguard Worker if (stringsOk)
2260*f6dc9357SAndroid Build Coastguard Worker stringsOk = ParseStringRes(item.ID, item.Lang, data, item.Size);
2261*f6dc9357SAndroid Build Coastguard Worker }
2262*f6dc9357SAndroid Build Coastguard Worker }
2263*f6dc9357SAndroid Build Coastguard Worker
2264*f6dc9357SAndroid Build Coastguard Worker if (item.IsVersion())
2265*f6dc9357SAndroid Build Coastguard Worker {
2266*f6dc9357SAndroid Build Coastguard Worker if (offset > _buf.Size() || _buf.Size() - offset < item.Size)
2267*f6dc9357SAndroid Build Coastguard Worker continue;
2268*f6dc9357SAndroid Build Coastguard Worker CTextFile f;
2269*f6dc9357SAndroid Build Coastguard Worker if (ParseVersion((const Byte *)_buf + offset, item.Size, f, _versionKeys))
2270*f6dc9357SAndroid Build Coastguard Worker {
2271*f6dc9357SAndroid Build Coastguard Worker CMixItem mixItem;
2272*f6dc9357SAndroid Build Coastguard Worker mixItem.VersionIndex = (int)_versionFiles.Size();
2273*f6dc9357SAndroid Build Coastguard Worker mixItem.SectionIndex = (int)sectionIndex; // check it !!!!
2274*f6dc9357SAndroid Build Coastguard Worker CByteBuffer_WithLang &vf = _versionFiles.AddNew();
2275*f6dc9357SAndroid Build Coastguard Worker vf.Lang = item.Lang;
2276*f6dc9357SAndroid Build Coastguard Worker vf.CopyFrom(f.Buf, f.Buf.GetPos());
2277*f6dc9357SAndroid Build Coastguard Worker _mixItems.Add(mixItem);
2278*f6dc9357SAndroid Build Coastguard Worker continue;
2279*f6dc9357SAndroid Build Coastguard Worker }
2280*f6dc9357SAndroid Build Coastguard Worker // PrintError("ver.Parse error");
2281*f6dc9357SAndroid Build Coastguard Worker }
2282*f6dc9357SAndroid Build Coastguard Worker
2283*f6dc9357SAndroid Build Coastguard Worker item.Enabled = true;
2284*f6dc9357SAndroid Build Coastguard Worker _items.Add(item);
2285*f6dc9357SAndroid Build Coastguard Worker }
2286*f6dc9357SAndroid Build Coastguard Worker }
2287*f6dc9357SAndroid Build Coastguard Worker }
2288*f6dc9357SAndroid Build Coastguard Worker
2289*f6dc9357SAndroid Build Coastguard Worker if (stringsOk && !_strings.IsEmpty())
2290*f6dc9357SAndroid Build Coastguard Worker {
2291*f6dc9357SAndroid Build Coastguard Worker unsigned i;
2292*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < _items.Size(); i++)
2293*f6dc9357SAndroid Build Coastguard Worker {
2294*f6dc9357SAndroid Build Coastguard Worker CResItem &item = _items[i];
2295*f6dc9357SAndroid Build Coastguard Worker if (item.IsString())
2296*f6dc9357SAndroid Build Coastguard Worker item.Enabled = false;
2297*f6dc9357SAndroid Build Coastguard Worker }
2298*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < _strings.Size(); i++)
2299*f6dc9357SAndroid Build Coastguard Worker {
2300*f6dc9357SAndroid Build Coastguard Worker if (_strings[i].FinalSize() == 0)
2301*f6dc9357SAndroid Build Coastguard Worker continue;
2302*f6dc9357SAndroid Build Coastguard Worker CMixItem mixItem;
2303*f6dc9357SAndroid Build Coastguard Worker mixItem.StringIndex = (int)i;
2304*f6dc9357SAndroid Build Coastguard Worker mixItem.SectionIndex = (int)sectionIndex;
2305*f6dc9357SAndroid Build Coastguard Worker _mixItems.Add(mixItem);
2306*f6dc9357SAndroid Build Coastguard Worker }
2307*f6dc9357SAndroid Build Coastguard Worker }
2308*f6dc9357SAndroid Build Coastguard Worker
2309*f6dc9357SAndroid Build Coastguard Worker _usedRes.Free();
2310*f6dc9357SAndroid Build Coastguard Worker
2311*f6dc9357SAndroid Build Coastguard Worker {
2312*f6dc9357SAndroid Build Coastguard Worker // PSize can be much larger than VSize in some exe installers.
2313*f6dc9357SAndroid Build Coastguard Worker // it contains archive data after PE resources.
2314*f6dc9357SAndroid Build Coastguard Worker // So we need to use PSize here!
2315*f6dc9357SAndroid Build Coastguard Worker if (maxOffset < sect.PSize)
2316*f6dc9357SAndroid Build Coastguard Worker {
2317*f6dc9357SAndroid Build Coastguard Worker size_t end = fileSize;
2318*f6dc9357SAndroid Build Coastguard Worker
2319*f6dc9357SAndroid Build Coastguard Worker // we skip Zeros to start of aligned block
2320*f6dc9357SAndroid Build Coastguard Worker size_t i;
2321*f6dc9357SAndroid Build Coastguard Worker for (i = maxOffset; i < end; i++)
2322*f6dc9357SAndroid Build Coastguard Worker if (_buf[i] != 0)
2323*f6dc9357SAndroid Build Coastguard Worker break;
2324*f6dc9357SAndroid Build Coastguard Worker if (i == end)
2325*f6dc9357SAndroid Build Coastguard Worker maxOffset = end;
2326*f6dc9357SAndroid Build Coastguard Worker
2327*f6dc9357SAndroid Build Coastguard Worker CSection sect2;
2328*f6dc9357SAndroid Build Coastguard Worker sect2.Flags = 0;
2329*f6dc9357SAndroid Build Coastguard Worker sect2.Pa = sect.Pa + (UInt32)maxOffset;
2330*f6dc9357SAndroid Build Coastguard Worker sect2.Va = sect.Va + (UInt32)maxOffset;
2331*f6dc9357SAndroid Build Coastguard Worker
2332*f6dc9357SAndroid Build Coastguard Worker // 9.29: we use sect.PSize instead of sect.VSize to support some CAB-SFX
2333*f6dc9357SAndroid Build Coastguard Worker // the code for .rsrc_2 is commented.
2334*f6dc9357SAndroid Build Coastguard Worker sect2.PSize = sect.PSize - (UInt32)maxOffset;
2335*f6dc9357SAndroid Build Coastguard Worker
2336*f6dc9357SAndroid Build Coastguard Worker if (sect2.PSize != 0)
2337*f6dc9357SAndroid Build Coastguard Worker {
2338*f6dc9357SAndroid Build Coastguard Worker sect2.ExtractSize = sect2.VSize = sect2.PSize;
2339*f6dc9357SAndroid Build Coastguard Worker sect2.Name = ".rsrc_1";
2340*f6dc9357SAndroid Build Coastguard Worker sect2.Time = 0;
2341*f6dc9357SAndroid Build Coastguard Worker sect2.IsAdditionalSection = true;
2342*f6dc9357SAndroid Build Coastguard Worker _sections.Add(sect2);
2343*f6dc9357SAndroid Build Coastguard Worker }
2344*f6dc9357SAndroid Build Coastguard Worker }
2345*f6dc9357SAndroid Build Coastguard Worker }
2346*f6dc9357SAndroid Build Coastguard Worker
2347*f6dc9357SAndroid Build Coastguard Worker return S_OK;
2348*f6dc9357SAndroid Build Coastguard Worker }
2349*f6dc9357SAndroid Build Coastguard Worker
2350*f6dc9357SAndroid Build Coastguard Worker
2351*f6dc9357SAndroid Build Coastguard Worker bool CHeader::ParseCoff(const Byte *p)
2352*f6dc9357SAndroid Build Coastguard Worker {
2353*f6dc9357SAndroid Build Coastguard Worker ParseBase(p);
2354*f6dc9357SAndroid Build Coastguard Worker if (PointerToSymbolTable < kCoffHeaderSize)
2355*f6dc9357SAndroid Build Coastguard Worker return false;
2356*f6dc9357SAndroid Build Coastguard Worker if (NumSymbols >= (1 << 24))
2357*f6dc9357SAndroid Build Coastguard Worker return false;
2358*f6dc9357SAndroid Build Coastguard Worker if (OptHeaderSize != 0 && OptHeaderSize < k_OptHeader32_Size_MIN)
2359*f6dc9357SAndroid Build Coastguard Worker return false;
2360*f6dc9357SAndroid Build Coastguard Worker
2361*f6dc9357SAndroid Build Coastguard Worker // 18.04: we reduce false detections
2362*f6dc9357SAndroid Build Coastguard Worker if (NumSections == 0 && OptHeaderSize == 0)
2363*f6dc9357SAndroid Build Coastguard Worker return false;
2364*f6dc9357SAndroid Build Coastguard Worker
2365*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_MachinePairs); i++)
2366*f6dc9357SAndroid Build Coastguard Worker if (Machine == g_MachinePairs[i].Value)
2367*f6dc9357SAndroid Build Coastguard Worker return true;
2368*f6dc9357SAndroid Build Coastguard Worker if (Machine == 0)
2369*f6dc9357SAndroid Build Coastguard Worker return true;
2370*f6dc9357SAndroid Build Coastguard Worker
2371*f6dc9357SAndroid Build Coastguard Worker return false;
2372*f6dc9357SAndroid Build Coastguard Worker }
2373*f6dc9357SAndroid Build Coastguard Worker
2374*f6dc9357SAndroid Build Coastguard Worker
2375*f6dc9357SAndroid Build Coastguard Worker static inline bool CheckPeOffset(UInt32 pe)
2376*f6dc9357SAndroid Build Coastguard Worker {
2377*f6dc9357SAndroid Build Coastguard Worker // ((pe & 7) == 0) is for most PE files. But there is unusual EFI-PE file that uses unaligned pe value.
2378*f6dc9357SAndroid Build Coastguard Worker return pe >= 0x40 && pe <= 0x1000 /* && (pe & 7) == 0 */ ;
2379*f6dc9357SAndroid Build Coastguard Worker }
2380*f6dc9357SAndroid Build Coastguard Worker
2381*f6dc9357SAndroid Build Coastguard Worker static const unsigned kStartSize = 0x40;
2382*f6dc9357SAndroid Build Coastguard Worker
2383*f6dc9357SAndroid Build Coastguard Worker API_FUNC_static_IsArc IsArc_Pe(const Byte *p, size_t size)
2384*f6dc9357SAndroid Build Coastguard Worker {
2385*f6dc9357SAndroid Build Coastguard Worker if (size < 2)
2386*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_NEED_MORE;
2387*f6dc9357SAndroid Build Coastguard Worker if (p[0] != 'M' || p[1] != 'Z')
2388*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_NO;
2389*f6dc9357SAndroid Build Coastguard Worker if (size < kStartSize)
2390*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_NEED_MORE;
2391*f6dc9357SAndroid Build Coastguard Worker UInt32 pe = Get32(p + 0x3C);
2392*f6dc9357SAndroid Build Coastguard Worker if (!CheckPeOffset(pe))
2393*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_NO;
2394*f6dc9357SAndroid Build Coastguard Worker if (pe + kPeHeaderSize > size)
2395*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_NEED_MORE;
2396*f6dc9357SAndroid Build Coastguard Worker CHeader header;
2397*f6dc9357SAndroid Build Coastguard Worker if (!header.ParsePe(p + pe))
2398*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_NO;
2399*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_YES;
2400*f6dc9357SAndroid Build Coastguard Worker }
2401*f6dc9357SAndroid Build Coastguard Worker }
2402*f6dc9357SAndroid Build Coastguard Worker
2403*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
2404*f6dc9357SAndroid Build Coastguard Worker {
2405*f6dc9357SAndroid Build Coastguard Worker UInt32 coffOffset = 0;
2406*f6dc9357SAndroid Build Coastguard Worker if (_coffMode)
2407*f6dc9357SAndroid Build Coastguard Worker {
2408*f6dc9357SAndroid Build Coastguard Worker Byte h[kCoffHeaderSize];
2409*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(stream, h, kCoffHeaderSize))
2410*f6dc9357SAndroid Build Coastguard Worker if (!_header.ParseCoff(h))
2411*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
2412*f6dc9357SAndroid Build Coastguard Worker }
2413*f6dc9357SAndroid Build Coastguard Worker else
2414*f6dc9357SAndroid Build Coastguard Worker {
2415*f6dc9357SAndroid Build Coastguard Worker UInt32 _peOffset;
2416*f6dc9357SAndroid Build Coastguard Worker {
2417*f6dc9357SAndroid Build Coastguard Worker Byte h[kStartSize];
2418*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(stream, h, kStartSize))
2419*f6dc9357SAndroid Build Coastguard Worker if (h[0] != 'M' || h[1] != 'Z')
2420*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
2421*f6dc9357SAndroid Build Coastguard Worker /* most of PE files contain 0x0090 at offset 2.
2422*f6dc9357SAndroid Build Coastguard Worker But some rare PE files contain another values. So we don't use that check.
2423*f6dc9357SAndroid Build Coastguard Worker if (Get16(h + 2) != 0x90) return false; */
2424*f6dc9357SAndroid Build Coastguard Worker _peOffset = Get32(h + 0x3C);
2425*f6dc9357SAndroid Build Coastguard Worker if (!CheckPeOffset(_peOffset))
2426*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
2427*f6dc9357SAndroid Build Coastguard Worker coffOffset = _peOffset + 4;
2428*f6dc9357SAndroid Build Coastguard Worker }
2429*f6dc9357SAndroid Build Coastguard Worker {
2430*f6dc9357SAndroid Build Coastguard Worker Byte h[kPeHeaderSize];
2431*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekSet(stream, _peOffset))
2432*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(stream, h, kPeHeaderSize))
2433*f6dc9357SAndroid Build Coastguard Worker if (!_header.ParsePe(h))
2434*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
2435*f6dc9357SAndroid Build Coastguard Worker }
2436*f6dc9357SAndroid Build Coastguard Worker }
2437*f6dc9357SAndroid Build Coastguard Worker
2438*f6dc9357SAndroid Build Coastguard Worker const UInt32 optStart = coffOffset + kCoffHeaderSize;
2439*f6dc9357SAndroid Build Coastguard Worker const UInt32 bufSize = _header.OptHeaderSize + (UInt32)_header.NumSections * kSectionSize;
2440*f6dc9357SAndroid Build Coastguard Worker _totalSize = optStart + bufSize;
2441*f6dc9357SAndroid Build Coastguard Worker CByteBuffer buffer(bufSize);
2442*f6dc9357SAndroid Build Coastguard Worker
2443*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(stream, buffer, bufSize))
2444*f6dc9357SAndroid Build Coastguard Worker
2445*f6dc9357SAndroid Build Coastguard Worker // memset((void *)&_optHeader, 0, sizeof(_optHeader));
2446*f6dc9357SAndroid Build Coastguard Worker if (_header.OptHeaderSize != 0)
2447*f6dc9357SAndroid Build Coastguard Worker if (!_optHeader.Parse(buffer, _header.OptHeaderSize))
2448*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
2449*f6dc9357SAndroid Build Coastguard Worker
2450*f6dc9357SAndroid Build Coastguard Worker UInt32 pos = _header.OptHeaderSize;
2451*f6dc9357SAndroid Build Coastguard Worker unsigned i;
2452*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < _header.NumSections; i++, pos += kSectionSize)
2453*f6dc9357SAndroid Build Coastguard Worker {
2454*f6dc9357SAndroid Build Coastguard Worker CSection § = _sections.AddNew();
2455*f6dc9357SAndroid Build Coastguard Worker sect.Parse(buffer + pos);
2456*f6dc9357SAndroid Build Coastguard Worker sect.IsRealSect = true;
2457*f6dc9357SAndroid Build Coastguard Worker if (sect.Name.IsEqualTo(".reloc"))
2458*f6dc9357SAndroid Build Coastguard Worker {
2459*f6dc9357SAndroid Build Coastguard Worker const CDirLink &dl = _optHeader.DirItems[kDirLink_BASERELOC];
2460*f6dc9357SAndroid Build Coastguard Worker if (dl.Va == sect.Va &&
2461*f6dc9357SAndroid Build Coastguard Worker dl.Size <= sect.PSize)
2462*f6dc9357SAndroid Build Coastguard Worker sect.ExtractSize = dl.Size;
2463*f6dc9357SAndroid Build Coastguard Worker }
2464*f6dc9357SAndroid Build Coastguard Worker else if (sect.Name.IsEqualTo(".pdata"))
2465*f6dc9357SAndroid Build Coastguard Worker {
2466*f6dc9357SAndroid Build Coastguard Worker const CDirLink &dl = _optHeader.DirItems[kDirLink_EXCEPTION];
2467*f6dc9357SAndroid Build Coastguard Worker if (dl.Va == sect.Va &&
2468*f6dc9357SAndroid Build Coastguard Worker dl.Size <= sect.PSize)
2469*f6dc9357SAndroid Build Coastguard Worker sect.ExtractSize = dl.Size;
2470*f6dc9357SAndroid Build Coastguard Worker }
2471*f6dc9357SAndroid Build Coastguard Worker
2472*f6dc9357SAndroid Build Coastguard Worker /* PE pre-file in .hxs file has errors:
2473*f6dc9357SAndroid Build Coastguard Worker PSize of resource is larger than real size.
2474*f6dc9357SAndroid Build Coastguard Worker So it overlaps next ".its" section.
2475*f6dc9357SAndroid Build Coastguard Worker 7-zip before 22.02: we corrected it.
2476*f6dc9357SAndroid Build Coastguard Worker
2477*f6dc9357SAndroid Build Coastguard Worker 22.02: another bad case is possible in incorrect pe (exe) file:
2478*f6dc9357SAndroid Build Coastguard Worker PSize in .rsrc section is correct,
2479*f6dc9357SAndroid Build Coastguard Worker but next .reloc section has incorrect (Pa) that overlaps with .rsrc.
2480*f6dc9357SAndroid Build Coastguard Worker */
2481*f6dc9357SAndroid Build Coastguard Worker
2482*f6dc9357SAndroid Build Coastguard Worker if (i != 0)
2483*f6dc9357SAndroid Build Coastguard Worker {
2484*f6dc9357SAndroid Build Coastguard Worker const CSection &prev = _sections[i - 1];
2485*f6dc9357SAndroid Build Coastguard Worker if (prev.Pa < sect.Pa
2486*f6dc9357SAndroid Build Coastguard Worker && prev.Pa + prev.PSize > sect.Pa
2487*f6dc9357SAndroid Build Coastguard Worker && sect.PSize != 0
2488*f6dc9357SAndroid Build Coastguard Worker && prev.PSize != 0)
2489*f6dc9357SAndroid Build Coastguard Worker {
2490*f6dc9357SAndroid Build Coastguard Worker _sectionsError = true;
2491*f6dc9357SAndroid Build Coastguard Worker // PRF(printf("\n !!!! Section correction: %s\n ", prev.Name));
2492*f6dc9357SAndroid Build Coastguard Worker
2493*f6dc9357SAndroid Build Coastguard Worker /* we corrected that case in 7-zip before 22.02: */
2494*f6dc9357SAndroid Build Coastguard Worker // prev.PSize = sect.Pa - prev.Pa;
2495*f6dc9357SAndroid Build Coastguard Worker
2496*f6dc9357SAndroid Build Coastguard Worker /* 22.02: here we can try to change bad section position to expected postion.
2497*f6dc9357SAndroid Build Coastguard Worker but original Windows code probably will not do same things. */
2498*f6dc9357SAndroid Build Coastguard Worker // if (prev.PSize <= sect.Va - prev.Va) sect.Pa = prev.Pa + prev.PSize;
2499*f6dc9357SAndroid Build Coastguard Worker }
2500*f6dc9357SAndroid Build Coastguard Worker }
2501*f6dc9357SAndroid Build Coastguard Worker /* last ".its" section in hxs file has incorrect sect.PSize.
2502*f6dc9357SAndroid Build Coastguard Worker 7-zip before 22.02: we reduced section to real sect.VSize */
2503*f6dc9357SAndroid Build Coastguard Worker /*
2504*f6dc9357SAndroid Build Coastguard Worker if (sect.VSize == 24 && sect.PSize == 512 && i == (unsigned)_header.NumSections - 1)
2505*f6dc9357SAndroid Build Coastguard Worker sect.PSize = sect.VSize;
2506*f6dc9357SAndroid Build Coastguard Worker */
2507*f6dc9357SAndroid Build Coastguard Worker }
2508*f6dc9357SAndroid Build Coastguard Worker
2509*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < _sections.Size(); i++)
2510*f6dc9357SAndroid Build Coastguard Worker _sections[i].UpdateTotalSize(_totalSize);
2511*f6dc9357SAndroid Build Coastguard Worker
2512*f6dc9357SAndroid Build Coastguard Worker bool thereISDebug = false;
2513*f6dc9357SAndroid Build Coastguard Worker if (IsOpt())
2514*f6dc9357SAndroid Build Coastguard Worker {
2515*f6dc9357SAndroid Build Coastguard Worker RINOK(LoadDebugSections(stream, thereISDebug))
2516*f6dc9357SAndroid Build Coastguard Worker
2517*f6dc9357SAndroid Build Coastguard Worker const CDirLink &certLink = _optHeader.DirItems[kDirLink_Certificate];
2518*f6dc9357SAndroid Build Coastguard Worker if (certLink.Size != 0)
2519*f6dc9357SAndroid Build Coastguard Worker {
2520*f6dc9357SAndroid Build Coastguard Worker CSection § = _sections.AddNew();
2521*f6dc9357SAndroid Build Coastguard Worker sect.Name = "CERTIFICATE";
2522*f6dc9357SAndroid Build Coastguard Worker sect.Va = 0;
2523*f6dc9357SAndroid Build Coastguard Worker sect.Pa = certLink.Va;
2524*f6dc9357SAndroid Build Coastguard Worker sect.Set_Size_for_all(certLink.Size);
2525*f6dc9357SAndroid Build Coastguard Worker sect.UpdateTotalSize(_totalSize);
2526*f6dc9357SAndroid Build Coastguard Worker }
2527*f6dc9357SAndroid Build Coastguard Worker
2528*f6dc9357SAndroid Build Coastguard Worker if (thereISDebug)
2529*f6dc9357SAndroid Build Coastguard Worker {
2530*f6dc9357SAndroid Build Coastguard Worker /* sometime there is some data after debug section.
2531*f6dc9357SAndroid Build Coastguard Worker We don't see any reference in exe file to that data.
2532*f6dc9357SAndroid Build Coastguard Worker But we suppose that it's part of EXE file */
2533*f6dc9357SAndroid Build Coastguard Worker
2534*f6dc9357SAndroid Build Coastguard Worker const UInt32 kAlign = 1 << 12;
2535*f6dc9357SAndroid Build Coastguard Worker UInt32 alignPos = _totalSize & (kAlign - 1);
2536*f6dc9357SAndroid Build Coastguard Worker if (alignPos != 0)
2537*f6dc9357SAndroid Build Coastguard Worker {
2538*f6dc9357SAndroid Build Coastguard Worker UInt32 size = kAlign - alignPos;
2539*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekSet(stream, _totalSize))
2540*f6dc9357SAndroid Build Coastguard Worker buffer.Alloc(kAlign);
2541*f6dc9357SAndroid Build Coastguard Worker Byte *buf = buffer;
2542*f6dc9357SAndroid Build Coastguard Worker size_t processed = size;
2543*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream(stream, buf, &processed))
2544*f6dc9357SAndroid Build Coastguard Worker
2545*f6dc9357SAndroid Build Coastguard Worker /*
2546*f6dc9357SAndroid Build Coastguard Worker if (processed != 0)
2547*f6dc9357SAndroid Build Coastguard Worker {
2548*f6dc9357SAndroid Build Coastguard Worker printf("\ndata after debug %d, %d \n", (int)size, (int)processed);
2549*f6dc9357SAndroid Build Coastguard Worker fflush(stdout);
2550*f6dc9357SAndroid Build Coastguard Worker }
2551*f6dc9357SAndroid Build Coastguard Worker */
2552*f6dc9357SAndroid Build Coastguard Worker
2553*f6dc9357SAndroid Build Coastguard Worker size_t k;
2554*f6dc9357SAndroid Build Coastguard Worker for (k = 0; k < processed; k++)
2555*f6dc9357SAndroid Build Coastguard Worker if (buf[k] != 0)
2556*f6dc9357SAndroid Build Coastguard Worker break;
2557*f6dc9357SAndroid Build Coastguard Worker if (processed < size && processed < 100)
2558*f6dc9357SAndroid Build Coastguard Worker _totalSize += (UInt32)processed;
2559*f6dc9357SAndroid Build Coastguard Worker else if (((_totalSize + k) & 0x1FF) == 0 || processed < size)
2560*f6dc9357SAndroid Build Coastguard Worker _totalSize += (UInt32)k;
2561*f6dc9357SAndroid Build Coastguard Worker }
2562*f6dc9357SAndroid Build Coastguard Worker }
2563*f6dc9357SAndroid Build Coastguard Worker }
2564*f6dc9357SAndroid Build Coastguard Worker
2565*f6dc9357SAndroid Build Coastguard Worker if (_header.NumSymbols > 0 && _header.PointerToSymbolTable >= optStart)
2566*f6dc9357SAndroid Build Coastguard Worker {
2567*f6dc9357SAndroid Build Coastguard Worker if (_header.NumSymbols >= (1 << 24))
2568*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
2569*f6dc9357SAndroid Build Coastguard Worker UInt32 size = _header.NumSymbols * 18;
2570*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekSet(stream, (UInt64)_header.PointerToSymbolTable + size))
2571*f6dc9357SAndroid Build Coastguard Worker Byte buf[4];
2572*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(stream, buf, 4))
2573*f6dc9357SAndroid Build Coastguard Worker UInt32 size2 = Get32(buf);
2574*f6dc9357SAndroid Build Coastguard Worker if (size2 >= (1 << 28))
2575*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
2576*f6dc9357SAndroid Build Coastguard Worker size += size2;
2577*f6dc9357SAndroid Build Coastguard Worker
2578*f6dc9357SAndroid Build Coastguard Worker CSection § = _sections.AddNew();
2579*f6dc9357SAndroid Build Coastguard Worker sect.Name = "COFF_SYMBOLS";
2580*f6dc9357SAndroid Build Coastguard Worker sect.Va = 0;
2581*f6dc9357SAndroid Build Coastguard Worker sect.Pa = _header.PointerToSymbolTable;
2582*f6dc9357SAndroid Build Coastguard Worker sect.Set_Size_for_all(size);
2583*f6dc9357SAndroid Build Coastguard Worker sect.UpdateTotalSize(_totalSize);
2584*f6dc9357SAndroid Build Coastguard Worker }
2585*f6dc9357SAndroid Build Coastguard Worker
2586*f6dc9357SAndroid Build Coastguard Worker {
2587*f6dc9357SAndroid Build Coastguard Worker CObjectVector<CSection> sections = _sections;
2588*f6dc9357SAndroid Build Coastguard Worker sections.Sort();
2589*f6dc9357SAndroid Build Coastguard Worker UInt32 limit = (1 << 12);
2590*f6dc9357SAndroid Build Coastguard Worker unsigned num = 0;
2591*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (k, sections)
2592*f6dc9357SAndroid Build Coastguard Worker {
2593*f6dc9357SAndroid Build Coastguard Worker const CSection &s = sections[k];
2594*f6dc9357SAndroid Build Coastguard Worker if (s.Pa > limit)
2595*f6dc9357SAndroid Build Coastguard Worker {
2596*f6dc9357SAndroid Build Coastguard Worker CSection &s2 = _sections.AddNew();
2597*f6dc9357SAndroid Build Coastguard Worker s2.Pa = s2.Va = limit;
2598*f6dc9357SAndroid Build Coastguard Worker s2.Set_Size_for_all(s.Pa - limit);
2599*f6dc9357SAndroid Build Coastguard Worker s2.IsAdditionalSection = true;
2600*f6dc9357SAndroid Build Coastguard Worker s2.Name.Add_Char('[');
2601*f6dc9357SAndroid Build Coastguard Worker s2.Name.Add_UInt32(num++);
2602*f6dc9357SAndroid Build Coastguard Worker s2.Name.Add_Char(']');
2603*f6dc9357SAndroid Build Coastguard Worker limit = s.Pa;
2604*f6dc9357SAndroid Build Coastguard Worker }
2605*f6dc9357SAndroid Build Coastguard Worker UInt32 next = s.Pa + s.PSize;
2606*f6dc9357SAndroid Build Coastguard Worker if (next < s.Pa)
2607*f6dc9357SAndroid Build Coastguard Worker break;
2608*f6dc9357SAndroid Build Coastguard Worker if (next >= limit)
2609*f6dc9357SAndroid Build Coastguard Worker limit = next;
2610*f6dc9357SAndroid Build Coastguard Worker }
2611*f6dc9357SAndroid Build Coastguard Worker }
2612*f6dc9357SAndroid Build Coastguard Worker
2613*f6dc9357SAndroid Build Coastguard Worker
2614*f6dc9357SAndroid Build Coastguard Worker if (IsOpt())
2615*f6dc9357SAndroid Build Coastguard Worker if (_optHeader.CheckSum != 0)
2616*f6dc9357SAndroid Build Coastguard Worker {
2617*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekToBegin(stream))
2618*f6dc9357SAndroid Build Coastguard Worker UInt32 checkSum = 0;
2619*f6dc9357SAndroid Build Coastguard Worker RINOK(CalcCheckSum(stream, _totalSize, optStart + k_CheckSum_Field_Offset, checkSum))
2620*f6dc9357SAndroid Build Coastguard Worker _checksumError = (checkSum != _optHeader.CheckSum);
2621*f6dc9357SAndroid Build Coastguard Worker }
2622*f6dc9357SAndroid Build Coastguard Worker
2623*f6dc9357SAndroid Build Coastguard Worker
2624*f6dc9357SAndroid Build Coastguard Worker if (!_allowTail)
2625*f6dc9357SAndroid Build Coastguard Worker {
2626*f6dc9357SAndroid Build Coastguard Worker UInt64 fileSize;
2627*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_GetSize_SeekToEnd(stream, fileSize))
2628*f6dc9357SAndroid Build Coastguard Worker if (fileSize > _totalSize)
2629*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
2630*f6dc9357SAndroid Build Coastguard Worker }
2631*f6dc9357SAndroid Build Coastguard Worker
2632*f6dc9357SAndroid Build Coastguard Worker bool _parseResources = true;
2633*f6dc9357SAndroid Build Coastguard Worker // _parseResources = false; // for debug
2634*f6dc9357SAndroid Build Coastguard Worker
2635*f6dc9357SAndroid Build Coastguard Worker UInt64 mainSize = 0, mainSize2 = 0;
2636*f6dc9357SAndroid Build Coastguard Worker
2637*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < _sections.Size(); i++)
2638*f6dc9357SAndroid Build Coastguard Worker {
2639*f6dc9357SAndroid Build Coastguard Worker const CSection § = _sections[i];
2640*f6dc9357SAndroid Build Coastguard Worker if (IsOpt())
2641*f6dc9357SAndroid Build Coastguard Worker if (_parseResources && sect.Name == ".rsrc")
2642*f6dc9357SAndroid Build Coastguard Worker {
2643*f6dc9357SAndroid Build Coastguard Worker // 20.01: we try to parse only first copy of .rsrc section.
2644*f6dc9357SAndroid Build Coastguard Worker _parseResources = false;
2645*f6dc9357SAndroid Build Coastguard Worker const unsigned numMixItems = _mixItems.Size();
2646*f6dc9357SAndroid Build Coastguard Worker HRESULT res = OpenResources(i, stream, callback);
2647*f6dc9357SAndroid Build Coastguard Worker if (res == S_OK)
2648*f6dc9357SAndroid Build Coastguard Worker {
2649*f6dc9357SAndroid Build Coastguard Worker _resourcesPrefix = sect.Name.Ptr();
2650*f6dc9357SAndroid Build Coastguard Worker _resourcesPrefix.Add_PathSepar();
2651*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (j, _items)
2652*f6dc9357SAndroid Build Coastguard Worker {
2653*f6dc9357SAndroid Build Coastguard Worker const CResItem &item = _items[j];
2654*f6dc9357SAndroid Build Coastguard Worker if (item.Enabled)
2655*f6dc9357SAndroid Build Coastguard Worker {
2656*f6dc9357SAndroid Build Coastguard Worker CMixItem mixItem;
2657*f6dc9357SAndroid Build Coastguard Worker mixItem.SectionIndex = (int)i;
2658*f6dc9357SAndroid Build Coastguard Worker mixItem.ResourceIndex = (int)j;
2659*f6dc9357SAndroid Build Coastguard Worker if (item.IsRcDataOrUnknown())
2660*f6dc9357SAndroid Build Coastguard Worker {
2661*f6dc9357SAndroid Build Coastguard Worker if (item.Size >= mainSize)
2662*f6dc9357SAndroid Build Coastguard Worker {
2663*f6dc9357SAndroid Build Coastguard Worker mainSize2 = mainSize;
2664*f6dc9357SAndroid Build Coastguard Worker mainSize = item.Size;
2665*f6dc9357SAndroid Build Coastguard Worker _mainSubfile = (Int32)(int)_mixItems.Size();
2666*f6dc9357SAndroid Build Coastguard Worker }
2667*f6dc9357SAndroid Build Coastguard Worker else if (item.Size >= mainSize2)
2668*f6dc9357SAndroid Build Coastguard Worker mainSize2 = item.Size;
2669*f6dc9357SAndroid Build Coastguard Worker }
2670*f6dc9357SAndroid Build Coastguard Worker _mixItems.Add(mixItem);
2671*f6dc9357SAndroid Build Coastguard Worker }
2672*f6dc9357SAndroid Build Coastguard Worker }
2673*f6dc9357SAndroid Build Coastguard Worker // 9.29: .rsrc_2 code was commented.
2674*f6dc9357SAndroid Build Coastguard Worker // .rsrc_1 now must include that .rsrc_2 block.
2675*f6dc9357SAndroid Build Coastguard Worker /*
2676*f6dc9357SAndroid Build Coastguard Worker if (sect.PSize > sect.VSize)
2677*f6dc9357SAndroid Build Coastguard Worker {
2678*f6dc9357SAndroid Build Coastguard Worker int numBits = _optHeader.GetNumFileAlignBits();
2679*f6dc9357SAndroid Build Coastguard Worker if (numBits >= 0)
2680*f6dc9357SAndroid Build Coastguard Worker {
2681*f6dc9357SAndroid Build Coastguard Worker UInt32 mask = (1 << numBits) - 1;
2682*f6dc9357SAndroid Build Coastguard Worker UInt32 end = ((sect.VSize + mask) & ~mask);
2683*f6dc9357SAndroid Build Coastguard Worker
2684*f6dc9357SAndroid Build Coastguard Worker if (sect.PSize > end)
2685*f6dc9357SAndroid Build Coastguard Worker {
2686*f6dc9357SAndroid Build Coastguard Worker CSection §2 = _sections.AddNew();
2687*f6dc9357SAndroid Build Coastguard Worker sect2.Flags = 0;
2688*f6dc9357SAndroid Build Coastguard Worker sect2.Pa = sect.Pa + end;
2689*f6dc9357SAndroid Build Coastguard Worker sect2.Va = sect.Va + end;
2690*f6dc9357SAndroid Build Coastguard Worker sect2.PSize = sect.PSize - end;
2691*f6dc9357SAndroid Build Coastguard Worker sect2.VSize = sect2.PSize;
2692*f6dc9357SAndroid Build Coastguard Worker sect2.Name = ".rsrc_2";
2693*f6dc9357SAndroid Build Coastguard Worker sect2.Time = 0;
2694*f6dc9357SAndroid Build Coastguard Worker sect2.IsAdditionalSection = true;
2695*f6dc9357SAndroid Build Coastguard Worker }
2696*f6dc9357SAndroid Build Coastguard Worker }
2697*f6dc9357SAndroid Build Coastguard Worker }
2698*f6dc9357SAndroid Build Coastguard Worker */
2699*f6dc9357SAndroid Build Coastguard Worker continue;
2700*f6dc9357SAndroid Build Coastguard Worker }
2701*f6dc9357SAndroid Build Coastguard Worker if (res != S_FALSE)
2702*f6dc9357SAndroid Build Coastguard Worker return res;
2703*f6dc9357SAndroid Build Coastguard Worker _mixItems.DeleteFrom(numMixItems);
2704*f6dc9357SAndroid Build Coastguard Worker CloseResources();
2705*f6dc9357SAndroid Build Coastguard Worker }
2706*f6dc9357SAndroid Build Coastguard Worker
2707*f6dc9357SAndroid Build Coastguard Worker if (sect.IsAdditionalSection)
2708*f6dc9357SAndroid Build Coastguard Worker {
2709*f6dc9357SAndroid Build Coastguard Worker if (sect.PSize >= mainSize)
2710*f6dc9357SAndroid Build Coastguard Worker {
2711*f6dc9357SAndroid Build Coastguard Worker mainSize2 = mainSize;
2712*f6dc9357SAndroid Build Coastguard Worker mainSize = sect.PSize;
2713*f6dc9357SAndroid Build Coastguard Worker _mainSubfile = (Int32)(int)_mixItems.Size();
2714*f6dc9357SAndroid Build Coastguard Worker }
2715*f6dc9357SAndroid Build Coastguard Worker else if (sect.PSize >= mainSize2)
2716*f6dc9357SAndroid Build Coastguard Worker mainSize2 = sect.PSize;
2717*f6dc9357SAndroid Build Coastguard Worker }
2718*f6dc9357SAndroid Build Coastguard Worker
2719*f6dc9357SAndroid Build Coastguard Worker CMixItem mixItem;
2720*f6dc9357SAndroid Build Coastguard Worker mixItem.SectionIndex = (int)i;
2721*f6dc9357SAndroid Build Coastguard Worker _mixItems.Add(mixItem);
2722*f6dc9357SAndroid Build Coastguard Worker }
2723*f6dc9357SAndroid Build Coastguard Worker
2724*f6dc9357SAndroid Build Coastguard Worker if (mainSize2 >= (1 << 20) && mainSize < mainSize2 * 2)
2725*f6dc9357SAndroid Build Coastguard Worker _mainSubfile = -1;
2726*f6dc9357SAndroid Build Coastguard Worker
2727*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < _mixItems.Size(); i++)
2728*f6dc9357SAndroid Build Coastguard Worker {
2729*f6dc9357SAndroid Build Coastguard Worker const CMixItem &mixItem = _mixItems[i];
2730*f6dc9357SAndroid Build Coastguard Worker if (mixItem.StringIndex < 0 && mixItem.ResourceIndex < 0 && _sections[mixItem.SectionIndex].Name == "_winzip_")
2731*f6dc9357SAndroid Build Coastguard Worker {
2732*f6dc9357SAndroid Build Coastguard Worker _mainSubfile = (Int32)(int)i;
2733*f6dc9357SAndroid Build Coastguard Worker break;
2734*f6dc9357SAndroid Build Coastguard Worker }
2735*f6dc9357SAndroid Build Coastguard Worker }
2736*f6dc9357SAndroid Build Coastguard Worker
2737*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < _versionKeys.Size(); i++)
2738*f6dc9357SAndroid Build Coastguard Worker {
2739*f6dc9357SAndroid Build Coastguard Worker if (i != 0)
2740*f6dc9357SAndroid Build Coastguard Worker _versionFullString.Add_LF();
2741*f6dc9357SAndroid Build Coastguard Worker const CStringKeyValue &k = _versionKeys[i];
2742*f6dc9357SAndroid Build Coastguard Worker _versionFullString += k.Key;
2743*f6dc9357SAndroid Build Coastguard Worker _versionFullString += ": ";
2744*f6dc9357SAndroid Build Coastguard Worker _versionFullString += k.Value;
2745*f6dc9357SAndroid Build Coastguard Worker }
2746*f6dc9357SAndroid Build Coastguard Worker
2747*f6dc9357SAndroid Build Coastguard Worker {
2748*f6dc9357SAndroid Build Coastguard Worker int keyIndex = FindKey(_versionKeys, "OriginalFilename");
2749*f6dc9357SAndroid Build Coastguard Worker if (keyIndex >= 0)
2750*f6dc9357SAndroid Build Coastguard Worker _originalFilename = _versionKeys[keyIndex].Value;
2751*f6dc9357SAndroid Build Coastguard Worker }
2752*f6dc9357SAndroid Build Coastguard Worker {
2753*f6dc9357SAndroid Build Coastguard Worker int keyIndex = FindKey(_versionKeys, "FileDescription");
2754*f6dc9357SAndroid Build Coastguard Worker if (keyIndex >= 0)
2755*f6dc9357SAndroid Build Coastguard Worker _versionShortString = _versionKeys[keyIndex].Value;
2756*f6dc9357SAndroid Build Coastguard Worker }
2757*f6dc9357SAndroid Build Coastguard Worker {
2758*f6dc9357SAndroid Build Coastguard Worker int keyIndex = FindKey(_versionKeys, "FileVersion");
2759*f6dc9357SAndroid Build Coastguard Worker if (keyIndex >= 0)
2760*f6dc9357SAndroid Build Coastguard Worker {
2761*f6dc9357SAndroid Build Coastguard Worker _versionShortString.Add_Space();
2762*f6dc9357SAndroid Build Coastguard Worker _versionShortString += _versionKeys[keyIndex].Value;
2763*f6dc9357SAndroid Build Coastguard Worker }
2764*f6dc9357SAndroid Build Coastguard Worker }
2765*f6dc9357SAndroid Build Coastguard Worker
2766*f6dc9357SAndroid Build Coastguard Worker return S_OK;
2767*f6dc9357SAndroid Build Coastguard Worker }
2768*f6dc9357SAndroid Build Coastguard Worker
2769*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *callback))
2770*f6dc9357SAndroid Build Coastguard Worker {
2771*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
2772*f6dc9357SAndroid Build Coastguard Worker Close();
2773*f6dc9357SAndroid Build Coastguard Worker RINOK(Open2(inStream, callback))
2774*f6dc9357SAndroid Build Coastguard Worker _stream = inStream;
2775*f6dc9357SAndroid Build Coastguard Worker return S_OK;
2776*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
2777*f6dc9357SAndroid Build Coastguard Worker }
2778*f6dc9357SAndroid Build Coastguard Worker
2779*f6dc9357SAndroid Build Coastguard Worker void CHandler::CloseResources()
2780*f6dc9357SAndroid Build Coastguard Worker {
2781*f6dc9357SAndroid Build Coastguard Worker _usedRes.Free();
2782*f6dc9357SAndroid Build Coastguard Worker _items.Clear();
2783*f6dc9357SAndroid Build Coastguard Worker _strings.Clear();
2784*f6dc9357SAndroid Build Coastguard Worker _versionFiles.Clear();
2785*f6dc9357SAndroid Build Coastguard Worker _buf.Free();
2786*f6dc9357SAndroid Build Coastguard Worker _versionFullString.Empty();
2787*f6dc9357SAndroid Build Coastguard Worker _versionShortString.Empty();
2788*f6dc9357SAndroid Build Coastguard Worker _originalFilename.Empty();
2789*f6dc9357SAndroid Build Coastguard Worker _versionKeys.Clear();
2790*f6dc9357SAndroid Build Coastguard Worker }
2791*f6dc9357SAndroid Build Coastguard Worker
2792*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Close())
2793*f6dc9357SAndroid Build Coastguard Worker {
2794*f6dc9357SAndroid Build Coastguard Worker _totalSize = 0;
2795*f6dc9357SAndroid Build Coastguard Worker _checksumError = false;
2796*f6dc9357SAndroid Build Coastguard Worker _sectionsError = false;
2797*f6dc9357SAndroid Build Coastguard Worker _mainSubfile = -1;
2798*f6dc9357SAndroid Build Coastguard Worker
2799*f6dc9357SAndroid Build Coastguard Worker _stream.Release();
2800*f6dc9357SAndroid Build Coastguard Worker _sections.Clear();
2801*f6dc9357SAndroid Build Coastguard Worker _mixItems.Clear();
2802*f6dc9357SAndroid Build Coastguard Worker CloseResources();
2803*f6dc9357SAndroid Build Coastguard Worker return S_OK;
2804*f6dc9357SAndroid Build Coastguard Worker }
2805*f6dc9357SAndroid Build Coastguard Worker
2806*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
2807*f6dc9357SAndroid Build Coastguard Worker {
2808*f6dc9357SAndroid Build Coastguard Worker *numItems = _mixItems.Size();
2809*f6dc9357SAndroid Build Coastguard Worker return S_OK;
2810*f6dc9357SAndroid Build Coastguard Worker }
2811*f6dc9357SAndroid Build Coastguard Worker
2812*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
2813*f6dc9357SAndroid Build Coastguard Worker Int32 testMode, IArchiveExtractCallback *extractCallback))
2814*f6dc9357SAndroid Build Coastguard Worker {
2815*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
2816*f6dc9357SAndroid Build Coastguard Worker const bool allFilesMode = (numItems == (UInt32)(Int32)-1);
2817*f6dc9357SAndroid Build Coastguard Worker if (allFilesMode)
2818*f6dc9357SAndroid Build Coastguard Worker numItems = _mixItems.Size();
2819*f6dc9357SAndroid Build Coastguard Worker if (numItems == 0)
2820*f6dc9357SAndroid Build Coastguard Worker return S_OK;
2821*f6dc9357SAndroid Build Coastguard Worker UInt64 totalSize = 0;
2822*f6dc9357SAndroid Build Coastguard Worker UInt32 i;
2823*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < numItems; i++)
2824*f6dc9357SAndroid Build Coastguard Worker {
2825*f6dc9357SAndroid Build Coastguard Worker const CMixItem &mixItem = _mixItems[allFilesMode ? i : indices[i]];
2826*f6dc9357SAndroid Build Coastguard Worker UInt64 size;
2827*f6dc9357SAndroid Build Coastguard Worker if (mixItem.StringIndex >= 0)
2828*f6dc9357SAndroid Build Coastguard Worker size = _strings[mixItem.StringIndex].FinalSize();
2829*f6dc9357SAndroid Build Coastguard Worker else if (mixItem.VersionIndex >= 0)
2830*f6dc9357SAndroid Build Coastguard Worker size = _versionFiles[mixItem.VersionIndex].Size();
2831*f6dc9357SAndroid Build Coastguard Worker else if (mixItem.ResourceIndex >= 0)
2832*f6dc9357SAndroid Build Coastguard Worker size = _items[mixItem.ResourceIndex].GetSize();
2833*f6dc9357SAndroid Build Coastguard Worker else
2834*f6dc9357SAndroid Build Coastguard Worker size = _sections[mixItem.SectionIndex].GetSize_Extract();
2835*f6dc9357SAndroid Build Coastguard Worker totalSize += size;
2836*f6dc9357SAndroid Build Coastguard Worker }
2837*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetTotal(totalSize))
2838*f6dc9357SAndroid Build Coastguard Worker
2839*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
2840*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
2841*f6dc9357SAndroid Build Coastguard Worker lps->Init(extractCallback, false);
2842*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> inStream;
2843*f6dc9357SAndroid Build Coastguard Worker inStream->SetStream(_stream);
2844*f6dc9357SAndroid Build Coastguard Worker
2845*f6dc9357SAndroid Build Coastguard Worker totalSize = 0;
2846*f6dc9357SAndroid Build Coastguard Worker UInt64 currentItemSize;
2847*f6dc9357SAndroid Build Coastguard Worker
2848*f6dc9357SAndroid Build Coastguard Worker for (i = 0;; i++, totalSize += currentItemSize)
2849*f6dc9357SAndroid Build Coastguard Worker {
2850*f6dc9357SAndroid Build Coastguard Worker lps->InSize = lps->OutSize = totalSize;
2851*f6dc9357SAndroid Build Coastguard Worker RINOK(lps->SetCur())
2852*f6dc9357SAndroid Build Coastguard Worker if (i >= numItems)
2853*f6dc9357SAndroid Build Coastguard Worker break;
2854*f6dc9357SAndroid Build Coastguard Worker const Int32 askMode = testMode ?
2855*f6dc9357SAndroid Build Coastguard Worker NExtract::NAskMode::kTest :
2856*f6dc9357SAndroid Build Coastguard Worker NExtract::NAskMode::kExtract;
2857*f6dc9357SAndroid Build Coastguard Worker const UInt32 index = allFilesMode ? i : indices[i];
2858*f6dc9357SAndroid Build Coastguard Worker
2859*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialOutStream> outStream;
2860*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->GetStream(index, &outStream, askMode))
2861*f6dc9357SAndroid Build Coastguard Worker const CMixItem &mixItem = _mixItems[index];
2862*f6dc9357SAndroid Build Coastguard Worker
2863*f6dc9357SAndroid Build Coastguard Worker const CSection § = _sections[mixItem.SectionIndex];
2864*f6dc9357SAndroid Build Coastguard Worker bool isOk = true;
2865*f6dc9357SAndroid Build Coastguard Worker if (mixItem.StringIndex >= 0)
2866*f6dc9357SAndroid Build Coastguard Worker {
2867*f6dc9357SAndroid Build Coastguard Worker const CStringItem &item = _strings[mixItem.StringIndex];
2868*f6dc9357SAndroid Build Coastguard Worker currentItemSize = item.FinalSize();
2869*f6dc9357SAndroid Build Coastguard Worker if (!testMode && !outStream)
2870*f6dc9357SAndroid Build Coastguard Worker continue;
2871*f6dc9357SAndroid Build Coastguard Worker
2872*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->PrepareOperation(askMode))
2873*f6dc9357SAndroid Build Coastguard Worker if (outStream)
2874*f6dc9357SAndroid Build Coastguard Worker RINOK(WriteStream(outStream, item.Buf, item.FinalSize()))
2875*f6dc9357SAndroid Build Coastguard Worker }
2876*f6dc9357SAndroid Build Coastguard Worker else if (mixItem.VersionIndex >= 0)
2877*f6dc9357SAndroid Build Coastguard Worker {
2878*f6dc9357SAndroid Build Coastguard Worker const CByteBuffer &item = _versionFiles[mixItem.VersionIndex];
2879*f6dc9357SAndroid Build Coastguard Worker currentItemSize = item.Size();
2880*f6dc9357SAndroid Build Coastguard Worker if (!testMode && !outStream)
2881*f6dc9357SAndroid Build Coastguard Worker continue;
2882*f6dc9357SAndroid Build Coastguard Worker
2883*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->PrepareOperation(askMode))
2884*f6dc9357SAndroid Build Coastguard Worker if (outStream)
2885*f6dc9357SAndroid Build Coastguard Worker RINOK(WriteStream(outStream, item, item.Size()))
2886*f6dc9357SAndroid Build Coastguard Worker }
2887*f6dc9357SAndroid Build Coastguard Worker else if (mixItem.ResourceIndex >= 0)
2888*f6dc9357SAndroid Build Coastguard Worker {
2889*f6dc9357SAndroid Build Coastguard Worker const CResItem &item = _items[mixItem.ResourceIndex];
2890*f6dc9357SAndroid Build Coastguard Worker currentItemSize = item.GetSize();
2891*f6dc9357SAndroid Build Coastguard Worker if (!testMode && !outStream)
2892*f6dc9357SAndroid Build Coastguard Worker continue;
2893*f6dc9357SAndroid Build Coastguard Worker
2894*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->PrepareOperation(askMode))
2895*f6dc9357SAndroid Build Coastguard Worker size_t offset = item.Offset - sect.Va;
2896*f6dc9357SAndroid Build Coastguard Worker if (!CheckItem(sect, item, offset))
2897*f6dc9357SAndroid Build Coastguard Worker isOk = false;
2898*f6dc9357SAndroid Build Coastguard Worker else if (outStream)
2899*f6dc9357SAndroid Build Coastguard Worker {
2900*f6dc9357SAndroid Build Coastguard Worker if (item.HeaderSize != 0)
2901*f6dc9357SAndroid Build Coastguard Worker RINOK(WriteStream(outStream, item.Header, item.HeaderSize))
2902*f6dc9357SAndroid Build Coastguard Worker RINOK(WriteStream(outStream, _buf + offset, item.Size))
2903*f6dc9357SAndroid Build Coastguard Worker }
2904*f6dc9357SAndroid Build Coastguard Worker }
2905*f6dc9357SAndroid Build Coastguard Worker else
2906*f6dc9357SAndroid Build Coastguard Worker {
2907*f6dc9357SAndroid Build Coastguard Worker currentItemSize = sect.GetSize_Extract();
2908*f6dc9357SAndroid Build Coastguard Worker if (!testMode && !outStream)
2909*f6dc9357SAndroid Build Coastguard Worker continue;
2910*f6dc9357SAndroid Build Coastguard Worker
2911*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->PrepareOperation(askMode))
2912*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekSet(_stream, sect.Pa))
2913*f6dc9357SAndroid Build Coastguard Worker inStream->Init(currentItemSize);
2914*f6dc9357SAndroid Build Coastguard Worker RINOK(copyCoder.Interface()->Code(inStream, outStream, NULL, NULL, lps))
2915*f6dc9357SAndroid Build Coastguard Worker isOk = (copyCoder->TotalSize == currentItemSize);
2916*f6dc9357SAndroid Build Coastguard Worker }
2917*f6dc9357SAndroid Build Coastguard Worker
2918*f6dc9357SAndroid Build Coastguard Worker outStream.Release();
2919*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetOperationResult(isOk ?
2920*f6dc9357SAndroid Build Coastguard Worker NExtract::NOperationResult::kOK :
2921*f6dc9357SAndroid Build Coastguard Worker NExtract::NOperationResult::kDataError))
2922*f6dc9357SAndroid Build Coastguard Worker }
2923*f6dc9357SAndroid Build Coastguard Worker return S_OK;
2924*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
2925*f6dc9357SAndroid Build Coastguard Worker }
2926*f6dc9357SAndroid Build Coastguard Worker
2927*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))
2928*f6dc9357SAndroid Build Coastguard Worker {
2929*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
2930*f6dc9357SAndroid Build Coastguard Worker *stream = NULL;
2931*f6dc9357SAndroid Build Coastguard Worker
2932*f6dc9357SAndroid Build Coastguard Worker const CMixItem &mixItem = _mixItems[index];
2933*f6dc9357SAndroid Build Coastguard Worker const CSection § = _sections[mixItem.SectionIndex];
2934*f6dc9357SAndroid Build Coastguard Worker if (mixItem.IsSectionItem())
2935*f6dc9357SAndroid Build Coastguard Worker return CreateLimitedInStream(_stream, sect.Pa, sect.GetSize_Extract(), stream);
2936*f6dc9357SAndroid Build Coastguard Worker
2937*f6dc9357SAndroid Build Coastguard Worker CBufInStream *inStreamSpec = new CBufInStream;
2938*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialInStream> streamTemp = inStreamSpec;
2939*f6dc9357SAndroid Build Coastguard Worker CReferenceBuf *referenceBuf = new CReferenceBuf;
2940*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IUnknown> ref = referenceBuf;
2941*f6dc9357SAndroid Build Coastguard Worker if (mixItem.StringIndex >= 0)
2942*f6dc9357SAndroid Build Coastguard Worker {
2943*f6dc9357SAndroid Build Coastguard Worker const CStringItem &item = _strings[mixItem.StringIndex];
2944*f6dc9357SAndroid Build Coastguard Worker referenceBuf->Buf.CopyFrom(item.Buf, item.FinalSize());
2945*f6dc9357SAndroid Build Coastguard Worker }
2946*f6dc9357SAndroid Build Coastguard Worker else if (mixItem.VersionIndex >= 0)
2947*f6dc9357SAndroid Build Coastguard Worker {
2948*f6dc9357SAndroid Build Coastguard Worker const CByteBuffer &item = _versionFiles[mixItem.VersionIndex];
2949*f6dc9357SAndroid Build Coastguard Worker referenceBuf->Buf.CopyFrom(item, item.Size());
2950*f6dc9357SAndroid Build Coastguard Worker }
2951*f6dc9357SAndroid Build Coastguard Worker else
2952*f6dc9357SAndroid Build Coastguard Worker {
2953*f6dc9357SAndroid Build Coastguard Worker const CResItem &item = _items[mixItem.ResourceIndex];
2954*f6dc9357SAndroid Build Coastguard Worker size_t offset = item.Offset - sect.Va;
2955*f6dc9357SAndroid Build Coastguard Worker if (!CheckItem(sect, item, offset))
2956*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
2957*f6dc9357SAndroid Build Coastguard Worker if (item.HeaderSize == 0)
2958*f6dc9357SAndroid Build Coastguard Worker {
2959*f6dc9357SAndroid Build Coastguard Worker CBufInStream *streamSpec = new CBufInStream;
2960*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IInStream> streamTemp2 = streamSpec;
2961*f6dc9357SAndroid Build Coastguard Worker streamSpec->Init(_buf + offset, item.Size, (IInArchive *)this);
2962*f6dc9357SAndroid Build Coastguard Worker *stream = streamTemp2.Detach();
2963*f6dc9357SAndroid Build Coastguard Worker return S_OK;
2964*f6dc9357SAndroid Build Coastguard Worker }
2965*f6dc9357SAndroid Build Coastguard Worker referenceBuf->Buf.Alloc(item.HeaderSize + item.Size);
2966*f6dc9357SAndroid Build Coastguard Worker memcpy(referenceBuf->Buf, item.Header, item.HeaderSize);
2967*f6dc9357SAndroid Build Coastguard Worker if (item.Size != 0)
2968*f6dc9357SAndroid Build Coastguard Worker memcpy(referenceBuf->Buf + item.HeaderSize, _buf + offset, item.Size);
2969*f6dc9357SAndroid Build Coastguard Worker }
2970*f6dc9357SAndroid Build Coastguard Worker inStreamSpec->Init(referenceBuf);
2971*f6dc9357SAndroid Build Coastguard Worker
2972*f6dc9357SAndroid Build Coastguard Worker *stream = streamTemp.Detach();
2973*f6dc9357SAndroid Build Coastguard Worker return S_OK;
2974*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
2975*f6dc9357SAndroid Build Coastguard Worker }
2976*f6dc9357SAndroid Build Coastguard Worker
2977*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::AllowTail(Int32 allowTail))
2978*f6dc9357SAndroid Build Coastguard Worker {
2979*f6dc9357SAndroid Build Coastguard Worker _allowTail = IntToBool(allowTail);
2980*f6dc9357SAndroid Build Coastguard Worker return S_OK;
2981*f6dc9357SAndroid Build Coastguard Worker }
2982*f6dc9357SAndroid Build Coastguard Worker
2983*f6dc9357SAndroid Build Coastguard Worker static const Byte k_Signature[] = { 'M', 'Z' };
2984*f6dc9357SAndroid Build Coastguard Worker
2985*f6dc9357SAndroid Build Coastguard Worker REGISTER_ARC_I(
2986*f6dc9357SAndroid Build Coastguard Worker "PE", "exe dll sys", NULL, 0xDD,
2987*f6dc9357SAndroid Build Coastguard Worker k_Signature,
2988*f6dc9357SAndroid Build Coastguard Worker 0,
2989*f6dc9357SAndroid Build Coastguard Worker NArcInfoFlags::kPreArc,
2990*f6dc9357SAndroid Build Coastguard Worker IsArc_Pe)
2991*f6dc9357SAndroid Build Coastguard Worker
2992*f6dc9357SAndroid Build Coastguard Worker }
2993*f6dc9357SAndroid Build Coastguard Worker
2994*f6dc9357SAndroid Build Coastguard Worker namespace NCoff {
2995*f6dc9357SAndroid Build Coastguard Worker
2996*f6dc9357SAndroid Build Coastguard Worker API_FUNC_static_IsArc IsArc_Coff(const Byte *p, size_t size)
2997*f6dc9357SAndroid Build Coastguard Worker {
2998*f6dc9357SAndroid Build Coastguard Worker if (size < NPe::kCoffHeaderSize)
2999*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_NEED_MORE;
3000*f6dc9357SAndroid Build Coastguard Worker NPe::CHeader header;
3001*f6dc9357SAndroid Build Coastguard Worker if (!header.ParseCoff(p))
3002*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_NO;
3003*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_YES;
3004*f6dc9357SAndroid Build Coastguard Worker }
3005*f6dc9357SAndroid Build Coastguard Worker }
3006*f6dc9357SAndroid Build Coastguard Worker
3007*f6dc9357SAndroid Build Coastguard Worker /*
3008*f6dc9357SAndroid Build Coastguard Worker static const Byte k_Signature[] =
3009*f6dc9357SAndroid Build Coastguard Worker {
3010*f6dc9357SAndroid Build Coastguard Worker 2, 0x4C, 0x01, // x86
3011*f6dc9357SAndroid Build Coastguard Worker 2, 0x64, 0x86, // x64
3012*f6dc9357SAndroid Build Coastguard Worker 2, 0x64, 0xAA // ARM64
3013*f6dc9357SAndroid Build Coastguard Worker };
3014*f6dc9357SAndroid Build Coastguard Worker REGISTER_ARC_I_CLS(
3015*f6dc9357SAndroid Build Coastguard Worker */
3016*f6dc9357SAndroid Build Coastguard Worker
3017*f6dc9357SAndroid Build Coastguard Worker REGISTER_ARC_I_CLS_NO_SIG(
3018*f6dc9357SAndroid Build Coastguard Worker NPe::CHandler(true),
3019*f6dc9357SAndroid Build Coastguard Worker "COFF", "obj", NULL, 0xC6,
3020*f6dc9357SAndroid Build Coastguard Worker // k_Signature,
3021*f6dc9357SAndroid Build Coastguard Worker 0,
3022*f6dc9357SAndroid Build Coastguard Worker // NArcInfoFlags::kMultiSignature |
3023*f6dc9357SAndroid Build Coastguard Worker NArcInfoFlags::kStartOpen,
3024*f6dc9357SAndroid Build Coastguard Worker IsArc_Coff)
3025*f6dc9357SAndroid Build Coastguard Worker }
3026*f6dc9357SAndroid Build Coastguard Worker
3027*f6dc9357SAndroid Build Coastguard Worker
3028*f6dc9357SAndroid Build Coastguard Worker namespace NTe {
3029*f6dc9357SAndroid Build Coastguard Worker
3030*f6dc9357SAndroid Build Coastguard Worker // Terse Executable (TE) image
3031*f6dc9357SAndroid Build Coastguard Worker
3032*f6dc9357SAndroid Build Coastguard Worker struct CDataDir
3033*f6dc9357SAndroid Build Coastguard Worker {
3034*f6dc9357SAndroid Build Coastguard Worker UInt32 Va;
3035*f6dc9357SAndroid Build Coastguard Worker UInt32 Size;
3036*f6dc9357SAndroid Build Coastguard Worker
3037*f6dc9357SAndroid Build Coastguard Worker void Parse(const Byte *p)
3038*f6dc9357SAndroid Build Coastguard Worker {
3039*f6dc9357SAndroid Build Coastguard Worker G32(0, Va);
3040*f6dc9357SAndroid Build Coastguard Worker G32(4, Size);
3041*f6dc9357SAndroid Build Coastguard Worker }
3042*f6dc9357SAndroid Build Coastguard Worker };
3043*f6dc9357SAndroid Build Coastguard Worker
3044*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kHeaderSize = 40;
3045*f6dc9357SAndroid Build Coastguard Worker
3046*f6dc9357SAndroid Build Coastguard Worker static bool FindValue(const CUInt32PCharPair *pairs, unsigned num, UInt32 value)
3047*f6dc9357SAndroid Build Coastguard Worker {
3048*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < num; i++)
3049*f6dc9357SAndroid Build Coastguard Worker if (pairs[i].Value == value)
3050*f6dc9357SAndroid Build Coastguard Worker return true;
3051*f6dc9357SAndroid Build Coastguard Worker return false;
3052*f6dc9357SAndroid Build Coastguard Worker }
3053*f6dc9357SAndroid Build Coastguard Worker
3054*f6dc9357SAndroid Build Coastguard Worker #define MY_FIND_VALUE(pairs, val) FindValue(pairs, Z7_ARRAY_SIZE(pairs), val)
3055*f6dc9357SAndroid Build Coastguard Worker #define MY_FIND_VALUE_2(strings, val) (val < Z7_ARRAY_SIZE(strings) && strings[val])
3056*f6dc9357SAndroid Build Coastguard Worker
3057*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kNumSection_MAX = 32;
3058*f6dc9357SAndroid Build Coastguard Worker
3059*f6dc9357SAndroid Build Coastguard Worker struct CHeader
3060*f6dc9357SAndroid Build Coastguard Worker {
3061*f6dc9357SAndroid Build Coastguard Worker UInt16 Machine;
3062*f6dc9357SAndroid Build Coastguard Worker Byte NumSections;
3063*f6dc9357SAndroid Build Coastguard Worker Byte SubSystem;
3064*f6dc9357SAndroid Build Coastguard Worker UInt16 StrippedSize;
3065*f6dc9357SAndroid Build Coastguard Worker /*
3066*f6dc9357SAndroid Build Coastguard Worker UInt32 AddressOfEntryPoint;
3067*f6dc9357SAndroid Build Coastguard Worker UInt32 BaseOfCode;
3068*f6dc9357SAndroid Build Coastguard Worker UInt64 ImageBase;
3069*f6dc9357SAndroid Build Coastguard Worker */
3070*f6dc9357SAndroid Build Coastguard Worker CDataDir DataDir[2]; // base relocation and debug directory
3071*f6dc9357SAndroid Build Coastguard Worker
3072*f6dc9357SAndroid Build Coastguard Worker bool ConvertPa(UInt32 &pa) const
3073*f6dc9357SAndroid Build Coastguard Worker {
3074*f6dc9357SAndroid Build Coastguard Worker if (pa < StrippedSize)
3075*f6dc9357SAndroid Build Coastguard Worker return false;
3076*f6dc9357SAndroid Build Coastguard Worker pa = pa - StrippedSize + kHeaderSize;
3077*f6dc9357SAndroid Build Coastguard Worker return true;
3078*f6dc9357SAndroid Build Coastguard Worker }
3079*f6dc9357SAndroid Build Coastguard Worker bool Parse(const Byte *p);
3080*f6dc9357SAndroid Build Coastguard Worker };
3081*f6dc9357SAndroid Build Coastguard Worker
3082*f6dc9357SAndroid Build Coastguard Worker bool CHeader::Parse(const Byte *p)
3083*f6dc9357SAndroid Build Coastguard Worker {
3084*f6dc9357SAndroid Build Coastguard Worker NumSections = p[4];
3085*f6dc9357SAndroid Build Coastguard Worker if (NumSections > kNumSection_MAX)
3086*f6dc9357SAndroid Build Coastguard Worker return false;
3087*f6dc9357SAndroid Build Coastguard Worker SubSystem = p[5];
3088*f6dc9357SAndroid Build Coastguard Worker G16(2, Machine);
3089*f6dc9357SAndroid Build Coastguard Worker G16(6, StrippedSize);
3090*f6dc9357SAndroid Build Coastguard Worker /*
3091*f6dc9357SAndroid Build Coastguard Worker G32(8, AddressOfEntryPoint);
3092*f6dc9357SAndroid Build Coastguard Worker G32(12, BaseOfCode);
3093*f6dc9357SAndroid Build Coastguard Worker G64(16, ImageBase);
3094*f6dc9357SAndroid Build Coastguard Worker */
3095*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < 2; i++)
3096*f6dc9357SAndroid Build Coastguard Worker {
3097*f6dc9357SAndroid Build Coastguard Worker CDataDir &dd = DataDir[i];
3098*f6dc9357SAndroid Build Coastguard Worker dd.Parse(p + 24 + i * 8);
3099*f6dc9357SAndroid Build Coastguard Worker if (dd.Size >= ((UInt32)1 << 28))
3100*f6dc9357SAndroid Build Coastguard Worker return false;
3101*f6dc9357SAndroid Build Coastguard Worker }
3102*f6dc9357SAndroid Build Coastguard Worker return
3103*f6dc9357SAndroid Build Coastguard Worker MY_FIND_VALUE(NPe::g_MachinePairs, Machine) &&
3104*f6dc9357SAndroid Build Coastguard Worker MY_FIND_VALUE_2(NPe::g_SubSystems, SubSystem);
3105*f6dc9357SAndroid Build Coastguard Worker }
3106*f6dc9357SAndroid Build Coastguard Worker
3107*f6dc9357SAndroid Build Coastguard Worker API_FUNC_static_IsArc IsArc_Te(const Byte *p, size_t size)
3108*f6dc9357SAndroid Build Coastguard Worker {
3109*f6dc9357SAndroid Build Coastguard Worker if (size < 2)
3110*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_NEED_MORE;
3111*f6dc9357SAndroid Build Coastguard Worker if (p[0] != 'V' || p[1] != 'Z')
3112*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_NO;
3113*f6dc9357SAndroid Build Coastguard Worker if (size < kHeaderSize)
3114*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_NEED_MORE;
3115*f6dc9357SAndroid Build Coastguard Worker
3116*f6dc9357SAndroid Build Coastguard Worker CHeader h;
3117*f6dc9357SAndroid Build Coastguard Worker if (!h.Parse(p))
3118*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_NO;
3119*f6dc9357SAndroid Build Coastguard Worker return k_IsArc_Res_YES;
3120*f6dc9357SAndroid Build Coastguard Worker }
3121*f6dc9357SAndroid Build Coastguard Worker }
3122*f6dc9357SAndroid Build Coastguard Worker
3123*f6dc9357SAndroid Build Coastguard Worker
3124*f6dc9357SAndroid Build Coastguard Worker struct CSection
3125*f6dc9357SAndroid Build Coastguard Worker {
3126*f6dc9357SAndroid Build Coastguard Worker Byte Name[NPe::kNameSize];
3127*f6dc9357SAndroid Build Coastguard Worker
3128*f6dc9357SAndroid Build Coastguard Worker UInt32 ExtractSize;
3129*f6dc9357SAndroid Build Coastguard Worker UInt32 VSize;
3130*f6dc9357SAndroid Build Coastguard Worker UInt32 Va;
3131*f6dc9357SAndroid Build Coastguard Worker UInt32 PSize;
3132*f6dc9357SAndroid Build Coastguard Worker UInt32 Pa;
3133*f6dc9357SAndroid Build Coastguard Worker UInt32 Flags;
3134*f6dc9357SAndroid Build Coastguard Worker // UInt16 NumRelocs;
3135*f6dc9357SAndroid Build Coastguard Worker
3136*f6dc9357SAndroid Build Coastguard Worker void Parse(const Byte *p)
3137*f6dc9357SAndroid Build Coastguard Worker {
3138*f6dc9357SAndroid Build Coastguard Worker memcpy(Name, p, NPe::kNameSize);
3139*f6dc9357SAndroid Build Coastguard Worker G32(8, VSize);
3140*f6dc9357SAndroid Build Coastguard Worker G32(12, Va);
3141*f6dc9357SAndroid Build Coastguard Worker G32(16, PSize);
3142*f6dc9357SAndroid Build Coastguard Worker G32(20, Pa);
3143*f6dc9357SAndroid Build Coastguard Worker // G32(p + 32, NumRelocs);
3144*f6dc9357SAndroid Build Coastguard Worker G32(36, Flags);
3145*f6dc9357SAndroid Build Coastguard Worker ExtractSize = (VSize && VSize < PSize) ? VSize : PSize;
3146*f6dc9357SAndroid Build Coastguard Worker }
3147*f6dc9357SAndroid Build Coastguard Worker
3148*f6dc9357SAndroid Build Coastguard Worker bool Check() const
3149*f6dc9357SAndroid Build Coastguard Worker {
3150*f6dc9357SAndroid Build Coastguard Worker return
3151*f6dc9357SAndroid Build Coastguard Worker Pa <= ((UInt32)1 << 30) &&
3152*f6dc9357SAndroid Build Coastguard Worker PSize <= ((UInt32)1 << 30);
3153*f6dc9357SAndroid Build Coastguard Worker }
3154*f6dc9357SAndroid Build Coastguard Worker
3155*f6dc9357SAndroid Build Coastguard Worker UInt32 GetSize_Extract() const
3156*f6dc9357SAndroid Build Coastguard Worker {
3157*f6dc9357SAndroid Build Coastguard Worker return ExtractSize;
3158*f6dc9357SAndroid Build Coastguard Worker }
3159*f6dc9357SAndroid Build Coastguard Worker
3160*f6dc9357SAndroid Build Coastguard Worker void UpdateTotalSize(UInt32 &totalSize)
3161*f6dc9357SAndroid Build Coastguard Worker {
3162*f6dc9357SAndroid Build Coastguard Worker const UInt32 t = Pa + PSize;
3163*f6dc9357SAndroid Build Coastguard Worker if (totalSize < t)
3164*f6dc9357SAndroid Build Coastguard Worker totalSize = t;
3165*f6dc9357SAndroid Build Coastguard Worker }
3166*f6dc9357SAndroid Build Coastguard Worker };
3167*f6dc9357SAndroid Build Coastguard Worker
3168*f6dc9357SAndroid Build Coastguard Worker
3169*f6dc9357SAndroid Build Coastguard Worker Z7_CLASS_IMP_CHandler_IInArchive_2(
3170*f6dc9357SAndroid Build Coastguard Worker IInArchiveGetStream,
3171*f6dc9357SAndroid Build Coastguard Worker IArchiveAllowTail
3172*f6dc9357SAndroid Build Coastguard Worker )
3173*f6dc9357SAndroid Build Coastguard Worker CRecordVector<CSection> _items;
3174*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IInStream> _stream;
3175*f6dc9357SAndroid Build Coastguard Worker UInt32 _totalSize;
3176*f6dc9357SAndroid Build Coastguard Worker bool _allowTail;
3177*f6dc9357SAndroid Build Coastguard Worker CHeader _h;
3178*f6dc9357SAndroid Build Coastguard Worker
3179*f6dc9357SAndroid Build Coastguard Worker HRESULT Open2(IInStream *stream);
3180*f6dc9357SAndroid Build Coastguard Worker public:
3181*f6dc9357SAndroid Build Coastguard Worker CHandler(): _allowTail(false) {}
3182*f6dc9357SAndroid Build Coastguard Worker };
3183*f6dc9357SAndroid Build Coastguard Worker
3184*f6dc9357SAndroid Build Coastguard Worker static const Byte kProps[] =
3185*f6dc9357SAndroid Build Coastguard Worker {
3186*f6dc9357SAndroid Build Coastguard Worker kpidPath,
3187*f6dc9357SAndroid Build Coastguard Worker kpidSize,
3188*f6dc9357SAndroid Build Coastguard Worker kpidPackSize,
3189*f6dc9357SAndroid Build Coastguard Worker kpidVirtualSize,
3190*f6dc9357SAndroid Build Coastguard Worker kpidCharacts,
3191*f6dc9357SAndroid Build Coastguard Worker kpidOffset,
3192*f6dc9357SAndroid Build Coastguard Worker kpidVa
3193*f6dc9357SAndroid Build Coastguard Worker };
3194*f6dc9357SAndroid Build Coastguard Worker
3195*f6dc9357SAndroid Build Coastguard Worker enum
3196*f6dc9357SAndroid Build Coastguard Worker {
3197*f6dc9357SAndroid Build Coastguard Worker kpidSubSystem = kpidUserDefined
3198*f6dc9357SAndroid Build Coastguard Worker // , kpidImageBase
3199*f6dc9357SAndroid Build Coastguard Worker };
3200*f6dc9357SAndroid Build Coastguard Worker
3201*f6dc9357SAndroid Build Coastguard Worker static const CStatProp kArcProps[] =
3202*f6dc9357SAndroid Build Coastguard Worker {
3203*f6dc9357SAndroid Build Coastguard Worker // { NULL, kpidHeadersSize, VT_UI4 },
3204*f6dc9357SAndroid Build Coastguard Worker { NULL, kpidCpu, VT_BSTR},
3205*f6dc9357SAndroid Build Coastguard Worker { "Subsystem", kpidSubSystem, VT_BSTR },
3206*f6dc9357SAndroid Build Coastguard Worker // { "Image Base", kpidImageBase, VT_UI8 }
3207*f6dc9357SAndroid Build Coastguard Worker };
3208*f6dc9357SAndroid Build Coastguard Worker
3209*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_Props
3210*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_ArcProps_WITH_NAME
3211*f6dc9357SAndroid Build Coastguard Worker
3212*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
3213*f6dc9357SAndroid Build Coastguard Worker {
3214*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
3215*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop;
3216*f6dc9357SAndroid Build Coastguard Worker switch (propID)
3217*f6dc9357SAndroid Build Coastguard Worker {
3218*f6dc9357SAndroid Build Coastguard Worker case kpidPhySize: prop = _totalSize; break;
3219*f6dc9357SAndroid Build Coastguard Worker case kpidCpu: PAIR_TO_PROP(NPe::g_MachinePairs, _h.Machine, prop); break;
3220*f6dc9357SAndroid Build Coastguard Worker case kpidSubSystem: TYPE_TO_PROP(NPe::g_SubSystems, _h.SubSystem, prop); break;
3221*f6dc9357SAndroid Build Coastguard Worker /*
3222*f6dc9357SAndroid Build Coastguard Worker case kpidImageBase: prop = _h.ImageBase; break;
3223*f6dc9357SAndroid Build Coastguard Worker case kpidAddressOfEntryPoint: prop = _h.AddressOfEntryPoint; break;
3224*f6dc9357SAndroid Build Coastguard Worker case kpidBaseOfCode: prop = _h.BaseOfCode; break;
3225*f6dc9357SAndroid Build Coastguard Worker */
3226*f6dc9357SAndroid Build Coastguard Worker }
3227*f6dc9357SAndroid Build Coastguard Worker prop.Detach(value);
3228*f6dc9357SAndroid Build Coastguard Worker return S_OK;
3229*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
3230*f6dc9357SAndroid Build Coastguard Worker }
3231*f6dc9357SAndroid Build Coastguard Worker
3232*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))
3233*f6dc9357SAndroid Build Coastguard Worker {
3234*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
3235*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop;
3236*f6dc9357SAndroid Build Coastguard Worker {
3237*f6dc9357SAndroid Build Coastguard Worker const CSection &item = _items[index];
3238*f6dc9357SAndroid Build Coastguard Worker switch (propID)
3239*f6dc9357SAndroid Build Coastguard Worker {
3240*f6dc9357SAndroid Build Coastguard Worker case kpidPath:
3241*f6dc9357SAndroid Build Coastguard Worker {
3242*f6dc9357SAndroid Build Coastguard Worker AString name;
3243*f6dc9357SAndroid Build Coastguard Worker NPe::GetName(item.Name, name);
3244*f6dc9357SAndroid Build Coastguard Worker prop = MultiByteToUnicodeString(name);
3245*f6dc9357SAndroid Build Coastguard Worker break;
3246*f6dc9357SAndroid Build Coastguard Worker }
3247*f6dc9357SAndroid Build Coastguard Worker case kpidSize: prop = (UInt64)item.GetSize_Extract(); break;
3248*f6dc9357SAndroid Build Coastguard Worker case kpidPackSize: prop = (UInt64)item.PSize; break;
3249*f6dc9357SAndroid Build Coastguard Worker case kpidVirtualSize: prop = (UInt64)item.VSize; break;
3250*f6dc9357SAndroid Build Coastguard Worker case kpidOffset: prop = item.Pa; break;
3251*f6dc9357SAndroid Build Coastguard Worker case kpidVa: prop = item.Va; break;
3252*f6dc9357SAndroid Build Coastguard Worker case kpidCharacts: FLAGS_TO_PROP(NPe::g_SectFlags, item.Flags, prop); break;
3253*f6dc9357SAndroid Build Coastguard Worker }
3254*f6dc9357SAndroid Build Coastguard Worker }
3255*f6dc9357SAndroid Build Coastguard Worker prop.Detach(value);
3256*f6dc9357SAndroid Build Coastguard Worker return S_OK;
3257*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
3258*f6dc9357SAndroid Build Coastguard Worker }
3259*f6dc9357SAndroid Build Coastguard Worker
3260*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::Open2(IInStream *stream)
3261*f6dc9357SAndroid Build Coastguard Worker {
3262*f6dc9357SAndroid Build Coastguard Worker Byte h[kHeaderSize];
3263*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(stream, h, kHeaderSize))
3264*f6dc9357SAndroid Build Coastguard Worker if (h[0] != 'V' || h[1] != 'Z')
3265*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
3266*f6dc9357SAndroid Build Coastguard Worker if (!_h.Parse(h))
3267*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
3268*f6dc9357SAndroid Build Coastguard Worker
3269*f6dc9357SAndroid Build Coastguard Worker UInt32 headerSize = NPe::kSectionSize * (UInt32)_h.NumSections;
3270*f6dc9357SAndroid Build Coastguard Worker CByteArr buf(headerSize);
3271*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(stream, buf, headerSize))
3272*f6dc9357SAndroid Build Coastguard Worker headerSize += kHeaderSize;
3273*f6dc9357SAndroid Build Coastguard Worker
3274*f6dc9357SAndroid Build Coastguard Worker _totalSize = headerSize;
3275*f6dc9357SAndroid Build Coastguard Worker _items.ClearAndReserve(_h.NumSections);
3276*f6dc9357SAndroid Build Coastguard Worker for (UInt32 i = 0; i < _h.NumSections; i++)
3277*f6dc9357SAndroid Build Coastguard Worker {
3278*f6dc9357SAndroid Build Coastguard Worker CSection sect;
3279*f6dc9357SAndroid Build Coastguard Worker sect.Parse(buf + i * NPe::kSectionSize);
3280*f6dc9357SAndroid Build Coastguard Worker if (!_h.ConvertPa(sect.Pa))
3281*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
3282*f6dc9357SAndroid Build Coastguard Worker if (sect.Pa < headerSize)
3283*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
3284*f6dc9357SAndroid Build Coastguard Worker if (!sect.Check())
3285*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
3286*f6dc9357SAndroid Build Coastguard Worker _items.AddInReserved(sect);
3287*f6dc9357SAndroid Build Coastguard Worker sect.UpdateTotalSize(_totalSize);
3288*f6dc9357SAndroid Build Coastguard Worker }
3289*f6dc9357SAndroid Build Coastguard Worker
3290*f6dc9357SAndroid Build Coastguard Worker if (!_allowTail)
3291*f6dc9357SAndroid Build Coastguard Worker {
3292*f6dc9357SAndroid Build Coastguard Worker UInt64 fileSize;
3293*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_GetSize_SeekToEnd(stream, fileSize))
3294*f6dc9357SAndroid Build Coastguard Worker if (fileSize > _totalSize)
3295*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
3296*f6dc9357SAndroid Build Coastguard Worker }
3297*f6dc9357SAndroid Build Coastguard Worker
3298*f6dc9357SAndroid Build Coastguard Worker return S_OK;
3299*f6dc9357SAndroid Build Coastguard Worker }
3300*f6dc9357SAndroid Build Coastguard Worker
3301*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Open(IInStream *inStream,
3302*f6dc9357SAndroid Build Coastguard Worker const UInt64 * /* maxCheckStartPosition */,
3303*f6dc9357SAndroid Build Coastguard Worker IArchiveOpenCallback * /* openArchiveCallback */))
3304*f6dc9357SAndroid Build Coastguard Worker {
3305*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
3306*f6dc9357SAndroid Build Coastguard Worker Close();
3307*f6dc9357SAndroid Build Coastguard Worker // try
3308*f6dc9357SAndroid Build Coastguard Worker {
3309*f6dc9357SAndroid Build Coastguard Worker if (Open2(inStream) != S_OK)
3310*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
3311*f6dc9357SAndroid Build Coastguard Worker _stream = inStream;
3312*f6dc9357SAndroid Build Coastguard Worker }
3313*f6dc9357SAndroid Build Coastguard Worker // catch(...) { return S_FALSE; }
3314*f6dc9357SAndroid Build Coastguard Worker return S_OK;
3315*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
3316*f6dc9357SAndroid Build Coastguard Worker }
3317*f6dc9357SAndroid Build Coastguard Worker
3318*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Close())
3319*f6dc9357SAndroid Build Coastguard Worker {
3320*f6dc9357SAndroid Build Coastguard Worker _totalSize = 0;
3321*f6dc9357SAndroid Build Coastguard Worker _stream.Release();
3322*f6dc9357SAndroid Build Coastguard Worker _items.Clear();
3323*f6dc9357SAndroid Build Coastguard Worker return S_OK;
3324*f6dc9357SAndroid Build Coastguard Worker }
3325*f6dc9357SAndroid Build Coastguard Worker
3326*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
3327*f6dc9357SAndroid Build Coastguard Worker {
3328*f6dc9357SAndroid Build Coastguard Worker *numItems = _items.Size();
3329*f6dc9357SAndroid Build Coastguard Worker return S_OK;
3330*f6dc9357SAndroid Build Coastguard Worker }
3331*f6dc9357SAndroid Build Coastguard Worker
3332*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
3333*f6dc9357SAndroid Build Coastguard Worker Int32 testMode, IArchiveExtractCallback *extractCallback))
3334*f6dc9357SAndroid Build Coastguard Worker {
3335*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
3336*f6dc9357SAndroid Build Coastguard Worker const bool allFilesMode = (numItems == (UInt32)(Int32)-1);
3337*f6dc9357SAndroid Build Coastguard Worker if (allFilesMode)
3338*f6dc9357SAndroid Build Coastguard Worker numItems = _items.Size();
3339*f6dc9357SAndroid Build Coastguard Worker if (numItems == 0)
3340*f6dc9357SAndroid Build Coastguard Worker return S_OK;
3341*f6dc9357SAndroid Build Coastguard Worker UInt64 totalSize = 0;
3342*f6dc9357SAndroid Build Coastguard Worker UInt32 i;
3343*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < numItems; i++)
3344*f6dc9357SAndroid Build Coastguard Worker totalSize += _items[allFilesMode ? i : indices[i]].GetSize_Extract();
3345*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetTotal(totalSize))
3346*f6dc9357SAndroid Build Coastguard Worker
3347*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
3348*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
3349*f6dc9357SAndroid Build Coastguard Worker lps->Init(extractCallback, false);
3350*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> inStream;
3351*f6dc9357SAndroid Build Coastguard Worker inStream->SetStream(_stream);
3352*f6dc9357SAndroid Build Coastguard Worker
3353*f6dc9357SAndroid Build Coastguard Worker totalSize = 0;
3354*f6dc9357SAndroid Build Coastguard Worker
3355*f6dc9357SAndroid Build Coastguard Worker for (i = 0;; i++)
3356*f6dc9357SAndroid Build Coastguard Worker {
3357*f6dc9357SAndroid Build Coastguard Worker lps->InSize = lps->OutSize = totalSize;
3358*f6dc9357SAndroid Build Coastguard Worker RINOK(lps->SetCur())
3359*f6dc9357SAndroid Build Coastguard Worker if (i >= numItems)
3360*f6dc9357SAndroid Build Coastguard Worker break;
3361*f6dc9357SAndroid Build Coastguard Worker int opRes;
3362*f6dc9357SAndroid Build Coastguard Worker {
3363*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialOutStream> realOutStream;
3364*f6dc9357SAndroid Build Coastguard Worker const Int32 askMode = testMode ?
3365*f6dc9357SAndroid Build Coastguard Worker NExtract::NAskMode::kTest :
3366*f6dc9357SAndroid Build Coastguard Worker NExtract::NAskMode::kExtract;
3367*f6dc9357SAndroid Build Coastguard Worker const UInt32 index = allFilesMode ? i : indices[i];
3368*f6dc9357SAndroid Build Coastguard Worker const CSection &item = _items[index];
3369*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->GetStream(index, &realOutStream, askMode))
3370*f6dc9357SAndroid Build Coastguard Worker const UInt32 size = item.GetSize_Extract();
3371*f6dc9357SAndroid Build Coastguard Worker totalSize += size;
3372*f6dc9357SAndroid Build Coastguard Worker
3373*f6dc9357SAndroid Build Coastguard Worker if (!testMode && !realOutStream)
3374*f6dc9357SAndroid Build Coastguard Worker continue;
3375*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->PrepareOperation(askMode))
3376*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekSet(_stream, item.Pa))
3377*f6dc9357SAndroid Build Coastguard Worker inStream->Init(size);
3378*f6dc9357SAndroid Build Coastguard Worker RINOK(copyCoder.Interface()->Code(inStream, realOutStream, NULL, NULL, lps))
3379*f6dc9357SAndroid Build Coastguard Worker
3380*f6dc9357SAndroid Build Coastguard Worker opRes = (copyCoder->TotalSize == size) ?
3381*f6dc9357SAndroid Build Coastguard Worker NExtract::NOperationResult::kOK : (copyCoder->TotalSize < size) ?
3382*f6dc9357SAndroid Build Coastguard Worker NExtract::NOperationResult::kUnexpectedEnd :
3383*f6dc9357SAndroid Build Coastguard Worker NExtract::NOperationResult::kDataError;
3384*f6dc9357SAndroid Build Coastguard Worker }
3385*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetOperationResult(opRes))
3386*f6dc9357SAndroid Build Coastguard Worker }
3387*f6dc9357SAndroid Build Coastguard Worker return S_OK;
3388*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
3389*f6dc9357SAndroid Build Coastguard Worker }
3390*f6dc9357SAndroid Build Coastguard Worker
3391*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))
3392*f6dc9357SAndroid Build Coastguard Worker {
3393*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
3394*f6dc9357SAndroid Build Coastguard Worker const CSection &item = _items[index];
3395*f6dc9357SAndroid Build Coastguard Worker return CreateLimitedInStream(_stream, item.Pa, item.GetSize_Extract(), stream);
3396*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
3397*f6dc9357SAndroid Build Coastguard Worker }
3398*f6dc9357SAndroid Build Coastguard Worker
3399*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::AllowTail(Int32 allowTail))
3400*f6dc9357SAndroid Build Coastguard Worker {
3401*f6dc9357SAndroid Build Coastguard Worker _allowTail = IntToBool(allowTail);
3402*f6dc9357SAndroid Build Coastguard Worker return S_OK;
3403*f6dc9357SAndroid Build Coastguard Worker }
3404*f6dc9357SAndroid Build Coastguard Worker
3405*f6dc9357SAndroid Build Coastguard Worker static const Byte k_Signature[] = { 'V', 'Z' };
3406*f6dc9357SAndroid Build Coastguard Worker
3407*f6dc9357SAndroid Build Coastguard Worker REGISTER_ARC_I(
3408*f6dc9357SAndroid Build Coastguard Worker "TE", "te", NULL, 0xCF,
3409*f6dc9357SAndroid Build Coastguard Worker k_Signature,
3410*f6dc9357SAndroid Build Coastguard Worker 0,
3411*f6dc9357SAndroid Build Coastguard Worker NArcInfoFlags::kPreArc,
3412*f6dc9357SAndroid Build Coastguard Worker IsArc_Te)
3413*f6dc9357SAndroid Build Coastguard Worker
3414*f6dc9357SAndroid Build Coastguard Worker }
3415*f6dc9357SAndroid Build Coastguard Worker }
3416