xref: /aosp_15_r20/external/lzma/CPP/7zip/Archive/PeHandler.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
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 &sect, 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 &sect = _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 &sect = _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 &sect = _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 &sect = _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 &sect = _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 &sect = _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 &sect = _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 &sect2 = _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 &sect = _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 &sect = _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