xref: /aosp_15_r20/external/lzma/CPP/7zip/Archive/VmdkHandler.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker // VmdkHandler.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/ComTry.h"
10*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/IntToString.h"
11*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/StringConvert.h"
12*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/StringToInt.h"
13*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/UTFConvert.h"
14*f6dc9357SAndroid Build Coastguard Worker 
15*f6dc9357SAndroid Build Coastguard Worker #include "../../Windows/PropVariant.h"
16*f6dc9357SAndroid Build Coastguard Worker 
17*f6dc9357SAndroid Build Coastguard Worker #include "../Common/RegisterArc.h"
18*f6dc9357SAndroid Build Coastguard Worker #include "../Common/StreamObjects.h"
19*f6dc9357SAndroid Build Coastguard Worker #include "../Common/StreamUtils.h"
20*f6dc9357SAndroid Build Coastguard Worker 
21*f6dc9357SAndroid Build Coastguard Worker #include "../Compress/ZlibDecoder.h"
22*f6dc9357SAndroid Build Coastguard Worker 
23*f6dc9357SAndroid Build Coastguard Worker #include "HandlerCont.h"
24*f6dc9357SAndroid Build Coastguard Worker 
25*f6dc9357SAndroid Build Coastguard Worker using namespace NWindows;
26*f6dc9357SAndroid Build Coastguard Worker 
27*f6dc9357SAndroid Build Coastguard Worker namespace NArchive {
28*f6dc9357SAndroid Build Coastguard Worker namespace NVmdk {
29*f6dc9357SAndroid Build Coastguard Worker 
30*f6dc9357SAndroid Build Coastguard Worker #define Get16(p) GetUi16(p)
31*f6dc9357SAndroid Build Coastguard Worker #define Get32(p) GetUi32(p)
32*f6dc9357SAndroid Build Coastguard Worker #define Get64(p) GetUi64(p)
33*f6dc9357SAndroid Build Coastguard Worker 
34*f6dc9357SAndroid Build Coastguard Worker #define LE_16(offs, dest) dest = Get16(p + (offs))
35*f6dc9357SAndroid Build Coastguard Worker #define LE_32(offs, dest) dest = Get32(p + (offs))
36*f6dc9357SAndroid Build Coastguard Worker #define LE_64(offs, dest) dest = Get64(p + (offs))
37*f6dc9357SAndroid Build Coastguard Worker 
38*f6dc9357SAndroid Build Coastguard Worker 
39*f6dc9357SAndroid Build Coastguard Worker static const Byte k_Signature[] = { 'K', 'D', 'M', 'V' };
40*f6dc9357SAndroid Build Coastguard Worker 
41*f6dc9357SAndroid Build Coastguard Worker static const UInt32 k_Flags_NL         = (UInt32)1 << 0;
42*f6dc9357SAndroid Build Coastguard Worker // static const UInt32 k_Flags_RGD        = (UInt32)1 << 1;
43*f6dc9357SAndroid Build Coastguard Worker static const UInt32 k_Flags_ZeroGrain  = (UInt32)1 << 2;
44*f6dc9357SAndroid Build Coastguard Worker static const UInt32 k_Flags_Compressed = (UInt32)1 << 16;
45*f6dc9357SAndroid Build Coastguard Worker static const UInt32 k_Flags_Marker     = (UInt32)1 << 17;
46*f6dc9357SAndroid Build Coastguard Worker 
47*f6dc9357SAndroid Build Coastguard Worker static const unsigned k_NumMidBits = 9; // num bits for index in Grain Table
48*f6dc9357SAndroid Build Coastguard Worker 
49*f6dc9357SAndroid Build Coastguard Worker struct CHeader
50*f6dc9357SAndroid Build Coastguard Worker {
51*f6dc9357SAndroid Build Coastguard Worker   UInt32 flags;
52*f6dc9357SAndroid Build Coastguard Worker   UInt32 version;
53*f6dc9357SAndroid Build Coastguard Worker 
54*f6dc9357SAndroid Build Coastguard Worker   UInt64 capacity;
55*f6dc9357SAndroid Build Coastguard Worker   UInt64 grainSize;
56*f6dc9357SAndroid Build Coastguard Worker   UInt64 descriptorOffset;
57*f6dc9357SAndroid Build Coastguard Worker   UInt64 descriptorSize;
58*f6dc9357SAndroid Build Coastguard Worker 
59*f6dc9357SAndroid Build Coastguard Worker   UInt32 numGTEsPerGT;
60*f6dc9357SAndroid Build Coastguard Worker   UInt16 algo;
61*f6dc9357SAndroid Build Coastguard Worker   // Byte uncleanShutdown;
62*f6dc9357SAndroid Build Coastguard Worker   // UInt64 rgdOffset;
63*f6dc9357SAndroid Build Coastguard Worker   UInt64 gdOffset;
64*f6dc9357SAndroid Build Coastguard Worker   UInt64 overHead;
65*f6dc9357SAndroid Build Coastguard Worker 
Is_NLNArchive::NVmdk::CHeader66*f6dc9357SAndroid Build Coastguard Worker   bool Is_NL()         const { return (flags & k_Flags_NL) != 0; }
Is_ZeroGrainNArchive::NVmdk::CHeader67*f6dc9357SAndroid Build Coastguard Worker   bool Is_ZeroGrain()  const { return (flags & k_Flags_ZeroGrain) != 0; }
Is_CompressedNArchive::NVmdk::CHeader68*f6dc9357SAndroid Build Coastguard Worker   bool Is_Compressed() const { return (flags & k_Flags_Compressed) != 0; }
Is_MarkerNArchive::NVmdk::CHeader69*f6dc9357SAndroid Build Coastguard Worker   bool Is_Marker()     const { return (flags & k_Flags_Marker) != 0; }
70*f6dc9357SAndroid Build Coastguard Worker 
71*f6dc9357SAndroid Build Coastguard Worker   bool Parse(const Byte *p);
72*f6dc9357SAndroid Build Coastguard Worker 
IsSameImageForNArchive::NVmdk::CHeader73*f6dc9357SAndroid Build Coastguard Worker   bool IsSameImageFor(const CHeader &h) const
74*f6dc9357SAndroid Build Coastguard Worker   {
75*f6dc9357SAndroid Build Coastguard Worker     return flags == h.flags
76*f6dc9357SAndroid Build Coastguard Worker         && version == h.version
77*f6dc9357SAndroid Build Coastguard Worker         && capacity == h.capacity
78*f6dc9357SAndroid Build Coastguard Worker         && grainSize == h.grainSize
79*f6dc9357SAndroid Build Coastguard Worker         && algo == h.algo;
80*f6dc9357SAndroid Build Coastguard Worker   }
81*f6dc9357SAndroid Build Coastguard Worker };
82*f6dc9357SAndroid Build Coastguard Worker 
Parse(const Byte * p)83*f6dc9357SAndroid Build Coastguard Worker bool CHeader::Parse(const Byte *p)
84*f6dc9357SAndroid Build Coastguard Worker {
85*f6dc9357SAndroid Build Coastguard Worker   if (memcmp(p, k_Signature, sizeof(k_Signature)) != 0)
86*f6dc9357SAndroid Build Coastguard Worker     return false;
87*f6dc9357SAndroid Build Coastguard Worker 
88*f6dc9357SAndroid Build Coastguard Worker   LE_32 (0x04, version);
89*f6dc9357SAndroid Build Coastguard Worker   LE_32 (0x08, flags);
90*f6dc9357SAndroid Build Coastguard Worker   LE_64 (0x0C, capacity);
91*f6dc9357SAndroid Build Coastguard Worker   LE_64 (0x14, grainSize);
92*f6dc9357SAndroid Build Coastguard Worker   LE_64 (0x1C, descriptorOffset);
93*f6dc9357SAndroid Build Coastguard Worker   LE_64 (0x24, descriptorSize);
94*f6dc9357SAndroid Build Coastguard Worker   LE_32 (0x2C, numGTEsPerGT);
95*f6dc9357SAndroid Build Coastguard Worker   // LE_64 (0x30, rgdOffset);
96*f6dc9357SAndroid Build Coastguard Worker   LE_64 (0x38, gdOffset);
97*f6dc9357SAndroid Build Coastguard Worker   LE_64 (0x40, overHead);
98*f6dc9357SAndroid Build Coastguard Worker   // uncleanShutdown = buf[0x48];
99*f6dc9357SAndroid Build Coastguard Worker   LE_16(0x4D, algo);
100*f6dc9357SAndroid Build Coastguard Worker 
101*f6dc9357SAndroid Build Coastguard Worker   if (Is_NL() && Get32(p + 0x49) != 0x0A0D200A) // do we need Is_NL() check here?
102*f6dc9357SAndroid Build Coastguard Worker     return false;
103*f6dc9357SAndroid Build Coastguard Worker 
104*f6dc9357SAndroid Build Coastguard Worker   return (numGTEsPerGT == (1 << k_NumMidBits)) && (version <= 3);
105*f6dc9357SAndroid Build Coastguard Worker }
106*f6dc9357SAndroid Build Coastguard Worker 
107*f6dc9357SAndroid Build Coastguard Worker 
108*f6dc9357SAndroid Build Coastguard Worker enum
109*f6dc9357SAndroid Build Coastguard Worker {
110*f6dc9357SAndroid Build Coastguard Worker   k_Marker_END_OF_STREAM = 0,
111*f6dc9357SAndroid Build Coastguard Worker   k_Marker_GRAIN_TABLE   = 1,
112*f6dc9357SAndroid Build Coastguard Worker   k_Marker_GRAIN_DIR     = 2,
113*f6dc9357SAndroid Build Coastguard Worker   k_Marker_FOOTER        = 3
114*f6dc9357SAndroid Build Coastguard Worker };
115*f6dc9357SAndroid Build Coastguard Worker 
116*f6dc9357SAndroid Build Coastguard Worker struct CMarker
117*f6dc9357SAndroid Build Coastguard Worker {
118*f6dc9357SAndroid Build Coastguard Worker   UInt64 NumSectors;
119*f6dc9357SAndroid Build Coastguard Worker   UInt32 SpecSize; // = 0 for metadata sectors
120*f6dc9357SAndroid Build Coastguard Worker   UInt32 Type;
121*f6dc9357SAndroid Build Coastguard Worker 
ParseNArchive::NVmdk::CMarker122*f6dc9357SAndroid Build Coastguard Worker   void Parse(const Byte *p)
123*f6dc9357SAndroid Build Coastguard Worker   {
124*f6dc9357SAndroid Build Coastguard Worker     LE_64 (0, NumSectors);
125*f6dc9357SAndroid Build Coastguard Worker     LE_32 (8, SpecSize);
126*f6dc9357SAndroid Build Coastguard Worker     LE_32 (12, Type);
127*f6dc9357SAndroid Build Coastguard Worker   }
128*f6dc9357SAndroid Build Coastguard Worker };
129*f6dc9357SAndroid Build Coastguard Worker 
130*f6dc9357SAndroid Build Coastguard Worker 
Str_to_ValName(const AString & s,AString & name,AString & val)131*f6dc9357SAndroid Build Coastguard Worker static bool Str_to_ValName(const AString &s, AString &name, AString &val)
132*f6dc9357SAndroid Build Coastguard Worker {
133*f6dc9357SAndroid Build Coastguard Worker   name.Empty();
134*f6dc9357SAndroid Build Coastguard Worker   val.Empty();
135*f6dc9357SAndroid Build Coastguard Worker   int qu = s.Find('"');
136*f6dc9357SAndroid Build Coastguard Worker   int eq = s.Find('=');
137*f6dc9357SAndroid Build Coastguard Worker   if (eq < 0 || (qu >= 0 && eq > qu))
138*f6dc9357SAndroid Build Coastguard Worker     return false;
139*f6dc9357SAndroid Build Coastguard Worker   name.SetFrom(s.Ptr(), eq);
140*f6dc9357SAndroid Build Coastguard Worker   name.Trim();
141*f6dc9357SAndroid Build Coastguard Worker   val = s.Ptr(eq + 1);
142*f6dc9357SAndroid Build Coastguard Worker   val.Trim();
143*f6dc9357SAndroid Build Coastguard Worker   return true;
144*f6dc9357SAndroid Build Coastguard Worker }
145*f6dc9357SAndroid Build Coastguard Worker 
IsSpaceChar(char c)146*f6dc9357SAndroid Build Coastguard Worker static inline bool IsSpaceChar(char c)
147*f6dc9357SAndroid Build Coastguard Worker {
148*f6dc9357SAndroid Build Coastguard Worker   return (c == ' ' || c == '\t');
149*f6dc9357SAndroid Build Coastguard Worker }
150*f6dc9357SAndroid Build Coastguard Worker 
SkipSpaces(const char * s)151*f6dc9357SAndroid Build Coastguard Worker static const char *SkipSpaces(const char *s)
152*f6dc9357SAndroid Build Coastguard Worker {
153*f6dc9357SAndroid Build Coastguard Worker   for (;; s++)
154*f6dc9357SAndroid Build Coastguard Worker   {
155*f6dc9357SAndroid Build Coastguard Worker     char c = *s;
156*f6dc9357SAndroid Build Coastguard Worker     if (c == 0 || !IsSpaceChar(c))
157*f6dc9357SAndroid Build Coastguard Worker       return s;
158*f6dc9357SAndroid Build Coastguard Worker   }
159*f6dc9357SAndroid Build Coastguard Worker }
160*f6dc9357SAndroid Build Coastguard Worker 
161*f6dc9357SAndroid Build Coastguard Worker #define SKIP_SPACES(s) s = SkipSpaces(s);
162*f6dc9357SAndroid Build Coastguard Worker 
GetNextWord(const char * s,AString & dest)163*f6dc9357SAndroid Build Coastguard Worker static const char *GetNextWord(const char *s, AString &dest)
164*f6dc9357SAndroid Build Coastguard Worker {
165*f6dc9357SAndroid Build Coastguard Worker   dest.Empty();
166*f6dc9357SAndroid Build Coastguard Worker   SKIP_SPACES(s)
167*f6dc9357SAndroid Build Coastguard Worker   const char *start = s;
168*f6dc9357SAndroid Build Coastguard Worker   for (;; s++)
169*f6dc9357SAndroid Build Coastguard Worker   {
170*f6dc9357SAndroid Build Coastguard Worker     char c = *s;
171*f6dc9357SAndroid Build Coastguard Worker     if (c == 0 || IsSpaceChar(c))
172*f6dc9357SAndroid Build Coastguard Worker     {
173*f6dc9357SAndroid Build Coastguard Worker       dest.SetFrom(start, (unsigned)(s - start));
174*f6dc9357SAndroid Build Coastguard Worker       return s;
175*f6dc9357SAndroid Build Coastguard Worker     }
176*f6dc9357SAndroid Build Coastguard Worker   }
177*f6dc9357SAndroid Build Coastguard Worker }
178*f6dc9357SAndroid Build Coastguard Worker 
GetNextNumber(const char * s,UInt64 & val)179*f6dc9357SAndroid Build Coastguard Worker static const char *GetNextNumber(const char *s, UInt64 &val)
180*f6dc9357SAndroid Build Coastguard Worker {
181*f6dc9357SAndroid Build Coastguard Worker   SKIP_SPACES(s)
182*f6dc9357SAndroid Build Coastguard Worker   if (*s == 0)
183*f6dc9357SAndroid Build Coastguard Worker     return s;
184*f6dc9357SAndroid Build Coastguard Worker   const char *end;
185*f6dc9357SAndroid Build Coastguard Worker   val = ConvertStringToUInt64(s, &end);
186*f6dc9357SAndroid Build Coastguard Worker   char c = *end;
187*f6dc9357SAndroid Build Coastguard Worker   if (c != 0 && !IsSpaceChar(c))
188*f6dc9357SAndroid Build Coastguard Worker     return NULL;
189*f6dc9357SAndroid Build Coastguard Worker   return end;
190*f6dc9357SAndroid Build Coastguard Worker }
191*f6dc9357SAndroid Build Coastguard Worker 
192*f6dc9357SAndroid Build Coastguard Worker 
193*f6dc9357SAndroid Build Coastguard Worker struct CExtentInfo
194*f6dc9357SAndroid Build Coastguard Worker {
195*f6dc9357SAndroid Build Coastguard Worker   AString Access;    // RW, RDONLY, or NOACCESS
196*f6dc9357SAndroid Build Coastguard Worker   UInt64 NumSectors; // 512 bytes sectors
197*f6dc9357SAndroid Build Coastguard Worker   AString Type;      // FLAT, SPARSE, ZERO, VMFS, VMFSSPARSE, VMFSRDM, VMFSRAW
198*f6dc9357SAndroid Build Coastguard Worker   AString FileName;
199*f6dc9357SAndroid Build Coastguard Worker   UInt64 StartSector; // used for FLAT
200*f6dc9357SAndroid Build Coastguard Worker 
201*f6dc9357SAndroid Build Coastguard Worker   // for VMWare Player 9:
202*f6dc9357SAndroid Build Coastguard Worker   // PartitionUUID
203*f6dc9357SAndroid Build Coastguard Worker   // DeviceIdentifier
204*f6dc9357SAndroid Build Coastguard Worker 
IsType_ZERONArchive::NVmdk::CExtentInfo205*f6dc9357SAndroid Build Coastguard Worker   bool IsType_ZERO() const { return Type == "ZERO"; }
206*f6dc9357SAndroid Build Coastguard Worker   // bool IsType_FLAT() const { return Type == "FLAT"; }
IsType_FlatNArchive::NVmdk::CExtentInfo207*f6dc9357SAndroid Build Coastguard Worker   bool IsType_Flat() const { return Type == "FLAT" || Type == "VMFS" || Type == "VMFSRAW"; }
208*f6dc9357SAndroid Build Coastguard Worker 
209*f6dc9357SAndroid Build Coastguard Worker   bool Parse(const char *s);
210*f6dc9357SAndroid Build Coastguard Worker };
211*f6dc9357SAndroid Build Coastguard Worker 
Parse(const char * s)212*f6dc9357SAndroid Build Coastguard Worker bool CExtentInfo::Parse(const char *s)
213*f6dc9357SAndroid Build Coastguard Worker {
214*f6dc9357SAndroid Build Coastguard Worker   NumSectors = 0;
215*f6dc9357SAndroid Build Coastguard Worker   StartSector = 0;
216*f6dc9357SAndroid Build Coastguard Worker   Access.Empty();
217*f6dc9357SAndroid Build Coastguard Worker   Type.Empty();
218*f6dc9357SAndroid Build Coastguard Worker   FileName.Empty();
219*f6dc9357SAndroid Build Coastguard Worker 
220*f6dc9357SAndroid Build Coastguard Worker   s = GetNextWord(s, Access);
221*f6dc9357SAndroid Build Coastguard Worker   s = GetNextNumber(s, NumSectors);
222*f6dc9357SAndroid Build Coastguard Worker   if (!s)
223*f6dc9357SAndroid Build Coastguard Worker     return false;
224*f6dc9357SAndroid Build Coastguard Worker   s = GetNextWord(s, Type);
225*f6dc9357SAndroid Build Coastguard Worker 
226*f6dc9357SAndroid Build Coastguard Worker   if (Type.IsEmpty())
227*f6dc9357SAndroid Build Coastguard Worker     return false;
228*f6dc9357SAndroid Build Coastguard Worker 
229*f6dc9357SAndroid Build Coastguard Worker   SKIP_SPACES(s)
230*f6dc9357SAndroid Build Coastguard Worker 
231*f6dc9357SAndroid Build Coastguard Worker   if (IsType_ZERO())
232*f6dc9357SAndroid Build Coastguard Worker     return (*s == 0);
233*f6dc9357SAndroid Build Coastguard Worker 
234*f6dc9357SAndroid Build Coastguard Worker   if (*s != '\"')
235*f6dc9357SAndroid Build Coastguard Worker     return false;
236*f6dc9357SAndroid Build Coastguard Worker   s++;
237*f6dc9357SAndroid Build Coastguard Worker   {
238*f6dc9357SAndroid Build Coastguard Worker     const char *s2 = strchr(s, '\"');
239*f6dc9357SAndroid Build Coastguard Worker     if (!s2)
240*f6dc9357SAndroid Build Coastguard Worker       return false;
241*f6dc9357SAndroid Build Coastguard Worker     FileName.SetFrom(s, (unsigned)(s2 - s));
242*f6dc9357SAndroid Build Coastguard Worker     s = s2 + 1;
243*f6dc9357SAndroid Build Coastguard Worker   }
244*f6dc9357SAndroid Build Coastguard Worker   SKIP_SPACES(s)
245*f6dc9357SAndroid Build Coastguard Worker   if (*s == 0)
246*f6dc9357SAndroid Build Coastguard Worker     return true;
247*f6dc9357SAndroid Build Coastguard Worker 
248*f6dc9357SAndroid Build Coastguard Worker   s = GetNextNumber(s, StartSector);
249*f6dc9357SAndroid Build Coastguard Worker   if (!s)
250*f6dc9357SAndroid Build Coastguard Worker     return false;
251*f6dc9357SAndroid Build Coastguard Worker   return true;
252*f6dc9357SAndroid Build Coastguard Worker   // SKIP_SPACES(s);
253*f6dc9357SAndroid Build Coastguard Worker   // return (*s == 0);
254*f6dc9357SAndroid Build Coastguard Worker }
255*f6dc9357SAndroid Build Coastguard Worker 
256*f6dc9357SAndroid Build Coastguard Worker 
257*f6dc9357SAndroid Build Coastguard Worker struct CDescriptor
258*f6dc9357SAndroid Build Coastguard Worker {
259*f6dc9357SAndroid Build Coastguard Worker   AString CID;
260*f6dc9357SAndroid Build Coastguard Worker   AString parentCID;
261*f6dc9357SAndroid Build Coastguard Worker   AString createType;
262*f6dc9357SAndroid Build Coastguard Worker   // AString encoding; // UTF-8, windows-1252 - default is UTF-8
263*f6dc9357SAndroid Build Coastguard Worker 
264*f6dc9357SAndroid Build Coastguard Worker   CObjectVector<CExtentInfo> Extents;
265*f6dc9357SAndroid Build Coastguard Worker 
GetUnicodeNameNArchive::NVmdk::CDescriptor266*f6dc9357SAndroid Build Coastguard Worker   static void GetUnicodeName(const AString &s, UString &res)
267*f6dc9357SAndroid Build Coastguard Worker   {
268*f6dc9357SAndroid Build Coastguard Worker     if (!ConvertUTF8ToUnicode(s, res))
269*f6dc9357SAndroid Build Coastguard Worker       MultiByteToUnicodeString2(res, s);
270*f6dc9357SAndroid Build Coastguard Worker   }
271*f6dc9357SAndroid Build Coastguard Worker 
ClearNArchive::NVmdk::CDescriptor272*f6dc9357SAndroid Build Coastguard Worker   void Clear()
273*f6dc9357SAndroid Build Coastguard Worker   {
274*f6dc9357SAndroid Build Coastguard Worker     CID.Empty();
275*f6dc9357SAndroid Build Coastguard Worker     parentCID.Empty();
276*f6dc9357SAndroid Build Coastguard Worker     createType.Empty();
277*f6dc9357SAndroid Build Coastguard Worker     Extents.Clear();
278*f6dc9357SAndroid Build Coastguard Worker   }
279*f6dc9357SAndroid Build Coastguard Worker 
IsThere_ParentNArchive::NVmdk::CDescriptor280*f6dc9357SAndroid Build Coastguard Worker   bool IsThere_Parent() const
281*f6dc9357SAndroid Build Coastguard Worker   {
282*f6dc9357SAndroid Build Coastguard Worker     return !parentCID.IsEmpty() && !parentCID.IsEqualTo_Ascii_NoCase("ffffffff");
283*f6dc9357SAndroid Build Coastguard Worker   }
284*f6dc9357SAndroid Build Coastguard Worker 
285*f6dc9357SAndroid Build Coastguard Worker   bool Parse(const Byte *p, size_t size);
286*f6dc9357SAndroid Build Coastguard Worker };
287*f6dc9357SAndroid Build Coastguard Worker 
288*f6dc9357SAndroid Build Coastguard Worker 
Parse(const Byte * p,size_t size)289*f6dc9357SAndroid Build Coastguard Worker bool CDescriptor::Parse(const Byte *p, size_t size)
290*f6dc9357SAndroid Build Coastguard Worker {
291*f6dc9357SAndroid Build Coastguard Worker   Clear();
292*f6dc9357SAndroid Build Coastguard Worker 
293*f6dc9357SAndroid Build Coastguard Worker   AString s;
294*f6dc9357SAndroid Build Coastguard Worker   AString name;
295*f6dc9357SAndroid Build Coastguard Worker   AString val;
296*f6dc9357SAndroid Build Coastguard Worker 
297*f6dc9357SAndroid Build Coastguard Worker   for (;;)
298*f6dc9357SAndroid Build Coastguard Worker   {
299*f6dc9357SAndroid Build Coastguard Worker     Byte c = 0;
300*f6dc9357SAndroid Build Coastguard Worker     if (size != 0)
301*f6dc9357SAndroid Build Coastguard Worker     {
302*f6dc9357SAndroid Build Coastguard Worker       size--;
303*f6dc9357SAndroid Build Coastguard Worker       c = *p++;
304*f6dc9357SAndroid Build Coastguard Worker     }
305*f6dc9357SAndroid Build Coastguard Worker     if (c == 0 || c == 0xA || c == 0xD)
306*f6dc9357SAndroid Build Coastguard Worker     {
307*f6dc9357SAndroid Build Coastguard Worker       if (!s.IsEmpty() && s[0] != '#')
308*f6dc9357SAndroid Build Coastguard Worker       {
309*f6dc9357SAndroid Build Coastguard Worker         if (Str_to_ValName(s, name, val))
310*f6dc9357SAndroid Build Coastguard Worker         {
311*f6dc9357SAndroid Build Coastguard Worker           if (name.IsEqualTo_Ascii_NoCase("CID"))
312*f6dc9357SAndroid Build Coastguard Worker             CID = val;
313*f6dc9357SAndroid Build Coastguard Worker           else if (name.IsEqualTo_Ascii_NoCase("parentCID"))
314*f6dc9357SAndroid Build Coastguard Worker             parentCID = val;
315*f6dc9357SAndroid Build Coastguard Worker           else if (name.IsEqualTo_Ascii_NoCase("createType"))
316*f6dc9357SAndroid Build Coastguard Worker             createType = val;
317*f6dc9357SAndroid Build Coastguard Worker         }
318*f6dc9357SAndroid Build Coastguard Worker         else
319*f6dc9357SAndroid Build Coastguard Worker         {
320*f6dc9357SAndroid Build Coastguard Worker           CExtentInfo ei;
321*f6dc9357SAndroid Build Coastguard Worker           if (!ei.Parse(s))
322*f6dc9357SAndroid Build Coastguard Worker             return false;
323*f6dc9357SAndroid Build Coastguard Worker           Extents.Add(ei);
324*f6dc9357SAndroid Build Coastguard Worker         }
325*f6dc9357SAndroid Build Coastguard Worker       }
326*f6dc9357SAndroid Build Coastguard Worker 
327*f6dc9357SAndroid Build Coastguard Worker       s.Empty();
328*f6dc9357SAndroid Build Coastguard Worker       if (c == 0)
329*f6dc9357SAndroid Build Coastguard Worker         return true;
330*f6dc9357SAndroid Build Coastguard Worker     }
331*f6dc9357SAndroid Build Coastguard Worker     else
332*f6dc9357SAndroid Build Coastguard Worker       s += (char)c;
333*f6dc9357SAndroid Build Coastguard Worker   }
334*f6dc9357SAndroid Build Coastguard Worker }
335*f6dc9357SAndroid Build Coastguard Worker 
336*f6dc9357SAndroid Build Coastguard Worker 
337*f6dc9357SAndroid Build Coastguard Worker struct CExtent
338*f6dc9357SAndroid Build Coastguard Worker {
339*f6dc9357SAndroid Build Coastguard Worker   bool IsOK;
340*f6dc9357SAndroid Build Coastguard Worker   bool IsArc;
341*f6dc9357SAndroid Build Coastguard Worker   bool NeedDeflate;
342*f6dc9357SAndroid Build Coastguard Worker   bool Unsupported;
343*f6dc9357SAndroid Build Coastguard Worker   bool IsZero;
344*f6dc9357SAndroid Build Coastguard Worker   bool IsFlat;
345*f6dc9357SAndroid Build Coastguard Worker   bool DescriptorOK;
346*f6dc9357SAndroid Build Coastguard Worker   bool HeadersError;
347*f6dc9357SAndroid Build Coastguard Worker 
348*f6dc9357SAndroid Build Coastguard Worker   unsigned ClusterBits;
349*f6dc9357SAndroid Build Coastguard Worker   UInt32 ZeroSector;
350*f6dc9357SAndroid Build Coastguard Worker 
351*f6dc9357SAndroid Build Coastguard Worker   CObjectVector<CByteBuffer> Tables;
352*f6dc9357SAndroid Build Coastguard Worker 
353*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<IInStream> Stream;
354*f6dc9357SAndroid Build Coastguard Worker   UInt64 PosInArc;
355*f6dc9357SAndroid Build Coastguard Worker 
356*f6dc9357SAndroid Build Coastguard Worker   UInt64 PhySize;
357*f6dc9357SAndroid Build Coastguard Worker   UInt64 VirtSize;     // from vmdk header of volume
358*f6dc9357SAndroid Build Coastguard Worker 
359*f6dc9357SAndroid Build Coastguard Worker   UInt64 StartOffset;  // virtual offset of this extent
360*f6dc9357SAndroid Build Coastguard Worker   UInt64 NumBytes;     // from main descriptor, if multi-vol
361*f6dc9357SAndroid Build Coastguard Worker   UInt64 FlatOffset;   // in Stream
362*f6dc9357SAndroid Build Coastguard Worker 
363*f6dc9357SAndroid Build Coastguard Worker   CByteBuffer DescriptorBuf;
364*f6dc9357SAndroid Build Coastguard Worker   CDescriptor Descriptor;
365*f6dc9357SAndroid Build Coastguard Worker 
366*f6dc9357SAndroid Build Coastguard Worker   CHeader h;
367*f6dc9357SAndroid Build Coastguard Worker 
GetEndOffsetNArchive::NVmdk::CExtent368*f6dc9357SAndroid Build Coastguard Worker   UInt64 GetEndOffset() const { return StartOffset + NumBytes; }
369*f6dc9357SAndroid Build Coastguard Worker 
IsVmdkNArchive::NVmdk::CExtent370*f6dc9357SAndroid Build Coastguard Worker   bool IsVmdk() const { return !IsZero && !IsFlat; }
371*f6dc9357SAndroid Build Coastguard Worker   // if (IsOK && IsVmdk()), then VMDK header of this extent was read
372*f6dc9357SAndroid Build Coastguard Worker 
CExtentNArchive::NVmdk::CExtent373*f6dc9357SAndroid Build Coastguard Worker   CExtent():
374*f6dc9357SAndroid Build Coastguard Worker       IsOK(false),
375*f6dc9357SAndroid Build Coastguard Worker       IsArc(false),
376*f6dc9357SAndroid Build Coastguard Worker       NeedDeflate(false),
377*f6dc9357SAndroid Build Coastguard Worker       Unsupported(false),
378*f6dc9357SAndroid Build Coastguard Worker       IsZero(false),
379*f6dc9357SAndroid Build Coastguard Worker       IsFlat(false),
380*f6dc9357SAndroid Build Coastguard Worker       DescriptorOK(false),
381*f6dc9357SAndroid Build Coastguard Worker       HeadersError(false),
382*f6dc9357SAndroid Build Coastguard Worker 
383*f6dc9357SAndroid Build Coastguard Worker       ClusterBits(0),
384*f6dc9357SAndroid Build Coastguard Worker       ZeroSector(0),
385*f6dc9357SAndroid Build Coastguard Worker 
386*f6dc9357SAndroid Build Coastguard Worker       PosInArc(0),
387*f6dc9357SAndroid Build Coastguard Worker 
388*f6dc9357SAndroid Build Coastguard Worker       PhySize(0),
389*f6dc9357SAndroid Build Coastguard Worker       VirtSize(0),
390*f6dc9357SAndroid Build Coastguard Worker 
391*f6dc9357SAndroid Build Coastguard Worker       StartOffset(0),
392*f6dc9357SAndroid Build Coastguard Worker       NumBytes(0),
393*f6dc9357SAndroid Build Coastguard Worker       FlatOffset(0)
394*f6dc9357SAndroid Build Coastguard Worker         {}
395*f6dc9357SAndroid Build Coastguard Worker 
396*f6dc9357SAndroid Build Coastguard Worker 
397*f6dc9357SAndroid Build Coastguard Worker   HRESULT ReadForHeader(IInStream *stream, UInt64 sector, void *data, size_t numSectors);
398*f6dc9357SAndroid Build Coastguard Worker   HRESULT Open3(IInStream *stream, IArchiveOpenCallback *openCallback,
399*f6dc9357SAndroid Build Coastguard Worker         unsigned numVols, unsigned volIndex, UInt64 &complexity);
400*f6dc9357SAndroid Build Coastguard Worker 
SeekNArchive::NVmdk::CExtent401*f6dc9357SAndroid Build Coastguard Worker   HRESULT Seek(UInt64 offset)
402*f6dc9357SAndroid Build Coastguard Worker   {
403*f6dc9357SAndroid Build Coastguard Worker     PosInArc = offset;
404*f6dc9357SAndroid Build Coastguard Worker     return InStream_SeekSet(Stream, offset);
405*f6dc9357SAndroid Build Coastguard Worker   }
406*f6dc9357SAndroid Build Coastguard Worker 
InitAndSeekNArchive::NVmdk::CExtent407*f6dc9357SAndroid Build Coastguard Worker   HRESULT InitAndSeek()
408*f6dc9357SAndroid Build Coastguard Worker   {
409*f6dc9357SAndroid Build Coastguard Worker     if (Stream)
410*f6dc9357SAndroid Build Coastguard Worker       return Seek(0);
411*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
412*f6dc9357SAndroid Build Coastguard Worker   }
413*f6dc9357SAndroid Build Coastguard Worker 
ReadNArchive::NVmdk::CExtent414*f6dc9357SAndroid Build Coastguard Worker   HRESULT Read(void *data, size_t *size)
415*f6dc9357SAndroid Build Coastguard Worker   {
416*f6dc9357SAndroid Build Coastguard Worker     HRESULT res = ReadStream(Stream, data, size);
417*f6dc9357SAndroid Build Coastguard Worker     PosInArc += *size;
418*f6dc9357SAndroid Build Coastguard Worker     return res;
419*f6dc9357SAndroid Build Coastguard Worker   }
420*f6dc9357SAndroid Build Coastguard Worker };
421*f6dc9357SAndroid Build Coastguard Worker 
422*f6dc9357SAndroid Build Coastguard Worker 
423*f6dc9357SAndroid Build Coastguard Worker Z7_class_CHandler_final: public CHandlerImg
424*f6dc9357SAndroid Build Coastguard Worker {
425*f6dc9357SAndroid Build Coastguard Worker   bool _isArc;
426*f6dc9357SAndroid Build Coastguard Worker   bool _unsupported;
427*f6dc9357SAndroid Build Coastguard Worker   bool _unsupportedSome;
428*f6dc9357SAndroid Build Coastguard Worker   bool _headerError;
429*f6dc9357SAndroid Build Coastguard Worker   bool _missingVol;
430*f6dc9357SAndroid Build Coastguard Worker   bool _isMultiVol;
431*f6dc9357SAndroid Build Coastguard Worker   bool _needDeflate;
432*f6dc9357SAndroid Build Coastguard Worker 
433*f6dc9357SAndroid Build Coastguard Worker   UInt64 _cacheCluster;
434*f6dc9357SAndroid Build Coastguard Worker   unsigned _cacheExtent;
435*f6dc9357SAndroid Build Coastguard Worker   CByteBuffer _cache;
436*f6dc9357SAndroid Build Coastguard Worker   CByteBuffer _cacheCompressed;
437*f6dc9357SAndroid Build Coastguard Worker 
438*f6dc9357SAndroid Build Coastguard Worker   unsigned _clusterBitsMax;
439*f6dc9357SAndroid Build Coastguard Worker   UInt64 _phySize;
440*f6dc9357SAndroid Build Coastguard Worker 
441*f6dc9357SAndroid Build Coastguard Worker   CObjectVector<CExtent> _extents;
442*f6dc9357SAndroid Build Coastguard Worker 
443*f6dc9357SAndroid Build Coastguard Worker   CBufInStream *_bufInStreamSpec;
444*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<ISequentialInStream> _bufInStream;
445*f6dc9357SAndroid Build Coastguard Worker 
446*f6dc9357SAndroid Build Coastguard Worker   CBufPtrSeqOutStream *_bufOutStreamSpec;
447*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<ISequentialOutStream> _bufOutStream;
448*f6dc9357SAndroid Build Coastguard Worker 
449*f6dc9357SAndroid Build Coastguard Worker   NCompress::NZlib::CDecoder *_zlibDecoderSpec;
450*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<ICompressCoder> _zlibDecoder;
451*f6dc9357SAndroid Build Coastguard Worker 
452*f6dc9357SAndroid Build Coastguard Worker   CByteBuffer _descriptorBuf;
453*f6dc9357SAndroid Build Coastguard Worker   CDescriptor _descriptor;
454*f6dc9357SAndroid Build Coastguard Worker 
455*f6dc9357SAndroid Build Coastguard Worker   UString _missingVolName;
456*f6dc9357SAndroid Build Coastguard Worker 
457*f6dc9357SAndroid Build Coastguard Worker   void InitAndSeekMain()
458*f6dc9357SAndroid Build Coastguard Worker   {
459*f6dc9357SAndroid Build Coastguard Worker     _virtPos = 0;
460*f6dc9357SAndroid Build Coastguard Worker   }
461*f6dc9357SAndroid Build Coastguard Worker 
462*f6dc9357SAndroid Build Coastguard Worker   virtual HRESULT Open2(IInStream *stream, IArchiveOpenCallback *openCallback) Z7_override;
463*f6dc9357SAndroid Build Coastguard Worker   virtual void CloseAtError() Z7_override;
464*f6dc9357SAndroid Build Coastguard Worker public:
465*f6dc9357SAndroid Build Coastguard Worker   Z7_IFACE_COM7_IMP(IInArchive_Img)
466*f6dc9357SAndroid Build Coastguard Worker 
467*f6dc9357SAndroid Build Coastguard Worker   Z7_IFACE_COM7_IMP(IInArchiveGetStream)
468*f6dc9357SAndroid Build Coastguard Worker   Z7_IFACE_COM7_IMP(ISequentialInStream)
469*f6dc9357SAndroid Build Coastguard Worker };
470*f6dc9357SAndroid Build Coastguard Worker 
471*f6dc9357SAndroid Build Coastguard Worker 
472*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Read(void *data, UInt32 size, UInt32 *processedSize))
473*f6dc9357SAndroid Build Coastguard Worker {
474*f6dc9357SAndroid Build Coastguard Worker   if (processedSize)
475*f6dc9357SAndroid Build Coastguard Worker     *processedSize = 0;
476*f6dc9357SAndroid Build Coastguard Worker   if (_virtPos >= _size)
477*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
478*f6dc9357SAndroid Build Coastguard Worker   {
479*f6dc9357SAndroid Build Coastguard Worker     UInt64 rem = _size - _virtPos;
480*f6dc9357SAndroid Build Coastguard Worker     if (size > rem)
481*f6dc9357SAndroid Build Coastguard Worker       size = (UInt32)rem;
482*f6dc9357SAndroid Build Coastguard Worker     if (size == 0)
483*f6dc9357SAndroid Build Coastguard Worker       return S_OK;
484*f6dc9357SAndroid Build Coastguard Worker   }
485*f6dc9357SAndroid Build Coastguard Worker 
486*f6dc9357SAndroid Build Coastguard Worker   unsigned extentIndex;
487*f6dc9357SAndroid Build Coastguard Worker   {
488*f6dc9357SAndroid Build Coastguard Worker     unsigned left = 0, right = _extents.Size();
489*f6dc9357SAndroid Build Coastguard Worker     for (;;)
490*f6dc9357SAndroid Build Coastguard Worker     {
491*f6dc9357SAndroid Build Coastguard Worker       unsigned mid = (left + right) / 2;
492*f6dc9357SAndroid Build Coastguard Worker       if (mid == left)
493*f6dc9357SAndroid Build Coastguard Worker         break;
494*f6dc9357SAndroid Build Coastguard Worker       if (_virtPos < _extents[mid].StartOffset)
495*f6dc9357SAndroid Build Coastguard Worker         right = mid;
496*f6dc9357SAndroid Build Coastguard Worker       else
497*f6dc9357SAndroid Build Coastguard Worker         left = mid;
498*f6dc9357SAndroid Build Coastguard Worker     }
499*f6dc9357SAndroid Build Coastguard Worker     extentIndex = left;
500*f6dc9357SAndroid Build Coastguard Worker   }
501*f6dc9357SAndroid Build Coastguard Worker 
502*f6dc9357SAndroid Build Coastguard Worker   CExtent &extent = _extents[extentIndex];
503*f6dc9357SAndroid Build Coastguard Worker 
504*f6dc9357SAndroid Build Coastguard Worker   {
505*f6dc9357SAndroid Build Coastguard Worker     const UInt64 vir = _virtPos - extent.StartOffset;
506*f6dc9357SAndroid Build Coastguard Worker     if (vir >= extent.NumBytes)
507*f6dc9357SAndroid Build Coastguard Worker     {
508*f6dc9357SAndroid Build Coastguard Worker       return E_FAIL;
509*f6dc9357SAndroid Build Coastguard Worker       /*
510*f6dc9357SAndroid Build Coastguard Worker       if (vir > extent.NumBytes)
511*f6dc9357SAndroid Build Coastguard Worker         _stream_dataError = true;
512*f6dc9357SAndroid Build Coastguard Worker       memset(data, 0, size);
513*f6dc9357SAndroid Build Coastguard Worker       _virtPos += size;
514*f6dc9357SAndroid Build Coastguard Worker       if (processedSize)
515*f6dc9357SAndroid Build Coastguard Worker         *processedSize = size;
516*f6dc9357SAndroid Build Coastguard Worker       return S_OK;
517*f6dc9357SAndroid Build Coastguard Worker       */
518*f6dc9357SAndroid Build Coastguard Worker     }
519*f6dc9357SAndroid Build Coastguard Worker 
520*f6dc9357SAndroid Build Coastguard Worker     {
521*f6dc9357SAndroid Build Coastguard Worker       const UInt64 rem = extent.NumBytes - vir;
522*f6dc9357SAndroid Build Coastguard Worker       if (size > rem)
523*f6dc9357SAndroid Build Coastguard Worker         size = (UInt32)rem;
524*f6dc9357SAndroid Build Coastguard Worker     }
525*f6dc9357SAndroid Build Coastguard Worker 
526*f6dc9357SAndroid Build Coastguard Worker     if (vir >= extent.VirtSize)
527*f6dc9357SAndroid Build Coastguard Worker     {
528*f6dc9357SAndroid Build Coastguard Worker       // if vmdk's VirtSize is smaller than VirtSize from main multi-volume descriptor
529*f6dc9357SAndroid Build Coastguard Worker       _stream_dataError = true;
530*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
531*f6dc9357SAndroid Build Coastguard Worker       /*
532*f6dc9357SAndroid Build Coastguard Worker       memset(data, 0, size);
533*f6dc9357SAndroid Build Coastguard Worker       _virtPos += size;
534*f6dc9357SAndroid Build Coastguard Worker       if (processedSize)
535*f6dc9357SAndroid Build Coastguard Worker         *processedSize = size;
536*f6dc9357SAndroid Build Coastguard Worker       return S_OK;
537*f6dc9357SAndroid Build Coastguard Worker       */
538*f6dc9357SAndroid Build Coastguard Worker     }
539*f6dc9357SAndroid Build Coastguard Worker 
540*f6dc9357SAndroid Build Coastguard Worker     {
541*f6dc9357SAndroid Build Coastguard Worker       const UInt64 rem = extent.VirtSize - vir;
542*f6dc9357SAndroid Build Coastguard Worker       if (size > rem)
543*f6dc9357SAndroid Build Coastguard Worker         size = (UInt32)rem;
544*f6dc9357SAndroid Build Coastguard Worker     }
545*f6dc9357SAndroid Build Coastguard Worker 
546*f6dc9357SAndroid Build Coastguard Worker     if (extent.IsZero || !extent.IsOK || !extent.Stream || extent.Unsupported)
547*f6dc9357SAndroid Build Coastguard Worker     {
548*f6dc9357SAndroid Build Coastguard Worker       if (extent.Unsupported)
549*f6dc9357SAndroid Build Coastguard Worker       {
550*f6dc9357SAndroid Build Coastguard Worker         _stream_unsupportedMethod = true;
551*f6dc9357SAndroid Build Coastguard Worker         return S_FALSE;
552*f6dc9357SAndroid Build Coastguard Worker       }
553*f6dc9357SAndroid Build Coastguard Worker       if (!extent.IsOK || !extent.Stream)
554*f6dc9357SAndroid Build Coastguard Worker       {
555*f6dc9357SAndroid Build Coastguard Worker         _stream_unavailData = true;
556*f6dc9357SAndroid Build Coastguard Worker         return S_FALSE;
557*f6dc9357SAndroid Build Coastguard Worker       }
558*f6dc9357SAndroid Build Coastguard Worker       memset(data, 0, size);
559*f6dc9357SAndroid Build Coastguard Worker       _virtPos += size;
560*f6dc9357SAndroid Build Coastguard Worker       if (processedSize)
561*f6dc9357SAndroid Build Coastguard Worker         *processedSize = size;
562*f6dc9357SAndroid Build Coastguard Worker       return S_OK;
563*f6dc9357SAndroid Build Coastguard Worker     }
564*f6dc9357SAndroid Build Coastguard Worker 
565*f6dc9357SAndroid Build Coastguard Worker     if (extent.IsFlat)
566*f6dc9357SAndroid Build Coastguard Worker     {
567*f6dc9357SAndroid Build Coastguard Worker       UInt64 offset = extent.FlatOffset + vir;
568*f6dc9357SAndroid Build Coastguard Worker       if (offset != extent.PosInArc)
569*f6dc9357SAndroid Build Coastguard Worker       {
570*f6dc9357SAndroid Build Coastguard Worker         RINOK(extent.Seek(offset))
571*f6dc9357SAndroid Build Coastguard Worker       }
572*f6dc9357SAndroid Build Coastguard Worker       UInt32 size2 = 0;
573*f6dc9357SAndroid Build Coastguard Worker       HRESULT res = extent.Stream->Read(data, size, &size2);
574*f6dc9357SAndroid Build Coastguard Worker       if (res == S_OK && size2 == 0)
575*f6dc9357SAndroid Build Coastguard Worker       {
576*f6dc9357SAndroid Build Coastguard Worker         _stream_unavailData = true;
577*f6dc9357SAndroid Build Coastguard Worker         /*
578*f6dc9357SAndroid Build Coastguard Worker         memset(data, 0, size);
579*f6dc9357SAndroid Build Coastguard Worker         _virtPos += size;
580*f6dc9357SAndroid Build Coastguard Worker         if (processedSize)
581*f6dc9357SAndroid Build Coastguard Worker           *processedSize = size;
582*f6dc9357SAndroid Build Coastguard Worker         return S_OK;
583*f6dc9357SAndroid Build Coastguard Worker         */
584*f6dc9357SAndroid Build Coastguard Worker       }
585*f6dc9357SAndroid Build Coastguard Worker       // _stream_PackSize += size2;
586*f6dc9357SAndroid Build Coastguard Worker       extent.PosInArc += size2;
587*f6dc9357SAndroid Build Coastguard Worker       _virtPos += size2;
588*f6dc9357SAndroid Build Coastguard Worker       if (processedSize)
589*f6dc9357SAndroid Build Coastguard Worker         *processedSize = size2;
590*f6dc9357SAndroid Build Coastguard Worker       return res;
591*f6dc9357SAndroid Build Coastguard Worker     }
592*f6dc9357SAndroid Build Coastguard Worker   }
593*f6dc9357SAndroid Build Coastguard Worker 
594*f6dc9357SAndroid Build Coastguard Worker 
595*f6dc9357SAndroid Build Coastguard Worker   for (;;)
596*f6dc9357SAndroid Build Coastguard Worker   {
597*f6dc9357SAndroid Build Coastguard Worker     const UInt64 vir = _virtPos - extent.StartOffset;
598*f6dc9357SAndroid Build Coastguard Worker     const unsigned clusterBits = extent.ClusterBits;
599*f6dc9357SAndroid Build Coastguard Worker     const UInt64 cluster = vir >> clusterBits;
600*f6dc9357SAndroid Build Coastguard Worker     const size_t clusterSize = (size_t)1 << clusterBits;
601*f6dc9357SAndroid Build Coastguard Worker     const size_t lowBits = (size_t)vir & (clusterSize - 1);
602*f6dc9357SAndroid Build Coastguard Worker     {
603*f6dc9357SAndroid Build Coastguard Worker       size_t rem = clusterSize - lowBits;
604*f6dc9357SAndroid Build Coastguard Worker       if (size > rem)
605*f6dc9357SAndroid Build Coastguard Worker         size = (UInt32)rem;
606*f6dc9357SAndroid Build Coastguard Worker     }
607*f6dc9357SAndroid Build Coastguard Worker 
608*f6dc9357SAndroid Build Coastguard Worker     if (extentIndex == _cacheExtent && cluster == _cacheCluster)
609*f6dc9357SAndroid Build Coastguard Worker     {
610*f6dc9357SAndroid Build Coastguard Worker       memcpy(data, _cache + lowBits, size);
611*f6dc9357SAndroid Build Coastguard Worker       _virtPos += size;
612*f6dc9357SAndroid Build Coastguard Worker       if (processedSize)
613*f6dc9357SAndroid Build Coastguard Worker         *processedSize = size;
614*f6dc9357SAndroid Build Coastguard Worker       return S_OK;
615*f6dc9357SAndroid Build Coastguard Worker     }
616*f6dc9357SAndroid Build Coastguard Worker 
617*f6dc9357SAndroid Build Coastguard Worker     const UInt64 high = cluster >> k_NumMidBits;
618*f6dc9357SAndroid Build Coastguard Worker 
619*f6dc9357SAndroid Build Coastguard Worker     if (high < extent.Tables.Size())
620*f6dc9357SAndroid Build Coastguard Worker     {
621*f6dc9357SAndroid Build Coastguard Worker       const CByteBuffer &table = extent.Tables[(unsigned)high];
622*f6dc9357SAndroid Build Coastguard Worker 
623*f6dc9357SAndroid Build Coastguard Worker       if (table.Size() != 0)
624*f6dc9357SAndroid Build Coastguard Worker       {
625*f6dc9357SAndroid Build Coastguard Worker         const size_t midBits = (size_t)cluster & ((1 << k_NumMidBits) - 1);
626*f6dc9357SAndroid Build Coastguard Worker         const Byte *p = (const Byte *)table + (midBits << 2);
627*f6dc9357SAndroid Build Coastguard Worker         const UInt32 v = Get32(p);
628*f6dc9357SAndroid Build Coastguard Worker 
629*f6dc9357SAndroid Build Coastguard Worker         if (v != 0 && v != extent.ZeroSector)
630*f6dc9357SAndroid Build Coastguard Worker         {
631*f6dc9357SAndroid Build Coastguard Worker           UInt64 offset = (UInt64)v << 9;
632*f6dc9357SAndroid Build Coastguard Worker           if (extent.NeedDeflate)
633*f6dc9357SAndroid Build Coastguard Worker           {
634*f6dc9357SAndroid Build Coastguard Worker             if (offset != extent.PosInArc)
635*f6dc9357SAndroid Build Coastguard Worker             {
636*f6dc9357SAndroid Build Coastguard Worker               // printf("\n%12x %12x\n", (unsigned)offset, (unsigned)(offset - extent.PosInArc));
637*f6dc9357SAndroid Build Coastguard Worker               RINOK(extent.Seek(offset))
638*f6dc9357SAndroid Build Coastguard Worker             }
639*f6dc9357SAndroid Build Coastguard Worker 
640*f6dc9357SAndroid Build Coastguard Worker             const size_t kStartSize = 1 << 9;
641*f6dc9357SAndroid Build Coastguard Worker             {
642*f6dc9357SAndroid Build Coastguard Worker               size_t curSize = kStartSize;
643*f6dc9357SAndroid Build Coastguard Worker               RINOK(extent.Read(_cacheCompressed, &curSize))
644*f6dc9357SAndroid Build Coastguard Worker               // _stream_PackSize += curSize;
645*f6dc9357SAndroid Build Coastguard Worker               if (curSize != kStartSize)
646*f6dc9357SAndroid Build Coastguard Worker                 return S_FALSE;
647*f6dc9357SAndroid Build Coastguard Worker             }
648*f6dc9357SAndroid Build Coastguard Worker 
649*f6dc9357SAndroid Build Coastguard Worker             if (Get64(_cacheCompressed) != (cluster << (clusterBits - 9)))
650*f6dc9357SAndroid Build Coastguard Worker               return S_FALSE;
651*f6dc9357SAndroid Build Coastguard Worker 
652*f6dc9357SAndroid Build Coastguard Worker             UInt32 dataSize = Get32(_cacheCompressed + 8);
653*f6dc9357SAndroid Build Coastguard Worker             if (dataSize > ((UInt32)1 << 31))
654*f6dc9357SAndroid Build Coastguard Worker               return S_FALSE;
655*f6dc9357SAndroid Build Coastguard Worker 
656*f6dc9357SAndroid Build Coastguard Worker             size_t dataSize2 = (size_t)dataSize + 12;
657*f6dc9357SAndroid Build Coastguard Worker 
658*f6dc9357SAndroid Build Coastguard Worker             if (dataSize2 > kStartSize)
659*f6dc9357SAndroid Build Coastguard Worker             {
660*f6dc9357SAndroid Build Coastguard Worker               dataSize2 = (dataSize2 + 511) & ~(size_t)511;
661*f6dc9357SAndroid Build Coastguard Worker               if (dataSize2 > _cacheCompressed.Size())
662*f6dc9357SAndroid Build Coastguard Worker                 return S_FALSE;
663*f6dc9357SAndroid Build Coastguard Worker               size_t curSize = dataSize2 - kStartSize;
664*f6dc9357SAndroid Build Coastguard Worker               const size_t curSize2 = curSize;
665*f6dc9357SAndroid Build Coastguard Worker               RINOK(extent.Read(_cacheCompressed + kStartSize, &curSize))
666*f6dc9357SAndroid Build Coastguard Worker               // _stream_PackSize += curSize;
667*f6dc9357SAndroid Build Coastguard Worker               if (curSize != curSize2)
668*f6dc9357SAndroid Build Coastguard Worker                 return S_FALSE;
669*f6dc9357SAndroid Build Coastguard Worker             }
670*f6dc9357SAndroid Build Coastguard Worker 
671*f6dc9357SAndroid Build Coastguard Worker             _bufInStreamSpec->Init(_cacheCompressed + 12, dataSize);
672*f6dc9357SAndroid Build Coastguard Worker 
673*f6dc9357SAndroid Build Coastguard Worker             _cacheCluster = (UInt64)(Int64)-1;
674*f6dc9357SAndroid Build Coastguard Worker             _cacheExtent = (unsigned)(int)-1;
675*f6dc9357SAndroid Build Coastguard Worker 
676*f6dc9357SAndroid Build Coastguard Worker             if (_cache.Size() < clusterSize)
677*f6dc9357SAndroid Build Coastguard Worker               return E_FAIL;
678*f6dc9357SAndroid Build Coastguard Worker             _bufOutStreamSpec->Init(_cache, clusterSize);
679*f6dc9357SAndroid Build Coastguard Worker 
680*f6dc9357SAndroid Build Coastguard Worker             // Do we need to use smaller block than clusterSize for last cluster?
681*f6dc9357SAndroid Build Coastguard Worker             const UInt64 blockSize64 = clusterSize;
682*f6dc9357SAndroid Build Coastguard Worker             HRESULT res = _zlibDecoder->Code(_bufInStream, _bufOutStream, NULL, &blockSize64, NULL);
683*f6dc9357SAndroid Build Coastguard Worker 
684*f6dc9357SAndroid Build Coastguard Worker             /*
685*f6dc9357SAndroid Build Coastguard Worker             if (_bufOutStreamSpec->GetPos() != clusterSize)
686*f6dc9357SAndroid Build Coastguard Worker             {
687*f6dc9357SAndroid Build Coastguard Worker               _stream_dataError = true;
688*f6dc9357SAndroid Build Coastguard Worker               memset(_cache + _bufOutStreamSpec->GetPos(), 0, clusterSize - _bufOutStreamSpec->GetPos());
689*f6dc9357SAndroid Build Coastguard Worker             }
690*f6dc9357SAndroid Build Coastguard Worker             */
691*f6dc9357SAndroid Build Coastguard Worker 
692*f6dc9357SAndroid Build Coastguard Worker               if (_bufOutStreamSpec->GetPos() != clusterSize
693*f6dc9357SAndroid Build Coastguard Worker                   || _zlibDecoderSpec->GetInputProcessedSize() != dataSize)
694*f6dc9357SAndroid Build Coastguard Worker               {
695*f6dc9357SAndroid Build Coastguard Worker                 _stream_dataError = true;
696*f6dc9357SAndroid Build Coastguard Worker                 if (res == S_OK)
697*f6dc9357SAndroid Build Coastguard Worker                   res = S_FALSE;
698*f6dc9357SAndroid Build Coastguard Worker               }
699*f6dc9357SAndroid Build Coastguard Worker 
700*f6dc9357SAndroid Build Coastguard Worker             RINOK(res)
701*f6dc9357SAndroid Build Coastguard Worker 
702*f6dc9357SAndroid Build Coastguard Worker             _cacheCluster = cluster;
703*f6dc9357SAndroid Build Coastguard Worker             _cacheExtent = extentIndex;
704*f6dc9357SAndroid Build Coastguard Worker 
705*f6dc9357SAndroid Build Coastguard Worker             continue;
706*f6dc9357SAndroid Build Coastguard Worker             /*
707*f6dc9357SAndroid Build Coastguard Worker             memcpy(data, _cache + lowBits, size);
708*f6dc9357SAndroid Build Coastguard Worker             _virtPos += size;
709*f6dc9357SAndroid Build Coastguard Worker             if (processedSize)
710*f6dc9357SAndroid Build Coastguard Worker               *processedSize = size;
711*f6dc9357SAndroid Build Coastguard Worker             return S_OK;
712*f6dc9357SAndroid Build Coastguard Worker             */
713*f6dc9357SAndroid Build Coastguard Worker           }
714*f6dc9357SAndroid Build Coastguard Worker           {
715*f6dc9357SAndroid Build Coastguard Worker             offset += lowBits;
716*f6dc9357SAndroid Build Coastguard Worker             if (offset != extent.PosInArc)
717*f6dc9357SAndroid Build Coastguard Worker             {
718*f6dc9357SAndroid Build Coastguard Worker               // printf("\n%12x %12x\n", (unsigned)offset, (unsigned)(offset - extent.PosInArc));
719*f6dc9357SAndroid Build Coastguard Worker               RINOK(extent.Seek(offset))
720*f6dc9357SAndroid Build Coastguard Worker             }
721*f6dc9357SAndroid Build Coastguard Worker             UInt32 size2 = 0;
722*f6dc9357SAndroid Build Coastguard Worker             HRESULT res = extent.Stream->Read(data, size, &size2);
723*f6dc9357SAndroid Build Coastguard Worker             if (res == S_OK && size2 == 0)
724*f6dc9357SAndroid Build Coastguard Worker             {
725*f6dc9357SAndroid Build Coastguard Worker               _stream_unavailData = true;
726*f6dc9357SAndroid Build Coastguard Worker               /*
727*f6dc9357SAndroid Build Coastguard Worker               memset(data, 0, size);
728*f6dc9357SAndroid Build Coastguard Worker               _virtPos += size;
729*f6dc9357SAndroid Build Coastguard Worker               if (processedSize)
730*f6dc9357SAndroid Build Coastguard Worker                 *processedSize = size;
731*f6dc9357SAndroid Build Coastguard Worker               return S_OK;
732*f6dc9357SAndroid Build Coastguard Worker               */
733*f6dc9357SAndroid Build Coastguard Worker             }
734*f6dc9357SAndroid Build Coastguard Worker             extent.PosInArc += size2;
735*f6dc9357SAndroid Build Coastguard Worker             // _stream_PackSize += size2;
736*f6dc9357SAndroid Build Coastguard Worker             _virtPos += size2;
737*f6dc9357SAndroid Build Coastguard Worker             if (processedSize)
738*f6dc9357SAndroid Build Coastguard Worker               *processedSize = size2;
739*f6dc9357SAndroid Build Coastguard Worker             return res;
740*f6dc9357SAndroid Build Coastguard Worker           }
741*f6dc9357SAndroid Build Coastguard Worker         }
742*f6dc9357SAndroid Build Coastguard Worker       }
743*f6dc9357SAndroid Build Coastguard Worker     }
744*f6dc9357SAndroid Build Coastguard Worker 
745*f6dc9357SAndroid Build Coastguard Worker     memset(data, 0, size);
746*f6dc9357SAndroid Build Coastguard Worker     _virtPos += size;
747*f6dc9357SAndroid Build Coastguard Worker     if (processedSize)
748*f6dc9357SAndroid Build Coastguard Worker       *processedSize = size;
749*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
750*f6dc9357SAndroid Build Coastguard Worker   }
751*f6dc9357SAndroid Build Coastguard Worker }
752*f6dc9357SAndroid Build Coastguard Worker 
753*f6dc9357SAndroid Build Coastguard Worker 
754*f6dc9357SAndroid Build Coastguard Worker static const Byte kProps[] =
755*f6dc9357SAndroid Build Coastguard Worker {
756*f6dc9357SAndroid Build Coastguard Worker   kpidSize,
757*f6dc9357SAndroid Build Coastguard Worker   kpidPackSize
758*f6dc9357SAndroid Build Coastguard Worker };
759*f6dc9357SAndroid Build Coastguard Worker 
760*f6dc9357SAndroid Build Coastguard Worker static const Byte kArcProps[] =
761*f6dc9357SAndroid Build Coastguard Worker {
762*f6dc9357SAndroid Build Coastguard Worker   kpidNumVolumes,
763*f6dc9357SAndroid Build Coastguard Worker   kpidTotalPhySize,
764*f6dc9357SAndroid Build Coastguard Worker   kpidMethod,
765*f6dc9357SAndroid Build Coastguard Worker   kpidClusterSize,
766*f6dc9357SAndroid Build Coastguard Worker   kpidHeadersSize,
767*f6dc9357SAndroid Build Coastguard Worker   kpidId,
768*f6dc9357SAndroid Build Coastguard Worker   kpidName,
769*f6dc9357SAndroid Build Coastguard Worker   kpidComment
770*f6dc9357SAndroid Build Coastguard Worker };
771*f6dc9357SAndroid Build Coastguard Worker 
772*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_Props
773*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_ArcProps
774*f6dc9357SAndroid Build Coastguard Worker 
775*f6dc9357SAndroid Build Coastguard Worker 
776*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
777*f6dc9357SAndroid Build Coastguard Worker {
778*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_BEGIN
779*f6dc9357SAndroid Build Coastguard Worker   NCOM::CPropVariant prop;
780*f6dc9357SAndroid Build Coastguard Worker 
781*f6dc9357SAndroid Build Coastguard Worker   const CExtent *e = NULL;
782*f6dc9357SAndroid Build Coastguard Worker   const CDescriptor *desc = NULL;
783*f6dc9357SAndroid Build Coastguard Worker 
784*f6dc9357SAndroid Build Coastguard Worker   if (_isMultiVol)
785*f6dc9357SAndroid Build Coastguard Worker     desc = &_descriptor;
786*f6dc9357SAndroid Build Coastguard Worker   else if (_extents.Size() == 1)
787*f6dc9357SAndroid Build Coastguard Worker   {
788*f6dc9357SAndroid Build Coastguard Worker     e = &_extents[0];
789*f6dc9357SAndroid Build Coastguard Worker     desc = &e->Descriptor;
790*f6dc9357SAndroid Build Coastguard Worker   }
791*f6dc9357SAndroid Build Coastguard Worker 
792*f6dc9357SAndroid Build Coastguard Worker   switch (propID)
793*f6dc9357SAndroid Build Coastguard Worker   {
794*f6dc9357SAndroid Build Coastguard Worker     case kpidMainSubfile: prop = (UInt32)0; break;
795*f6dc9357SAndroid Build Coastguard Worker     case kpidPhySize: if (_phySize != 0) prop = _phySize; break;
796*f6dc9357SAndroid Build Coastguard Worker     case kpidTotalPhySize:
797*f6dc9357SAndroid Build Coastguard Worker     {
798*f6dc9357SAndroid Build Coastguard Worker       UInt64 sum = _phySize;
799*f6dc9357SAndroid Build Coastguard Worker       if (_isMultiVol)
800*f6dc9357SAndroid Build Coastguard Worker       {
801*f6dc9357SAndroid Build Coastguard Worker         FOR_VECTOR (i, _extents)
802*f6dc9357SAndroid Build Coastguard Worker           sum += _extents[i].PhySize;
803*f6dc9357SAndroid Build Coastguard Worker       }
804*f6dc9357SAndroid Build Coastguard Worker       prop = sum;
805*f6dc9357SAndroid Build Coastguard Worker       break;
806*f6dc9357SAndroid Build Coastguard Worker     }
807*f6dc9357SAndroid Build Coastguard Worker     case kpidClusterSize: prop = (UInt32)((UInt32)1 << _clusterBitsMax); break;
808*f6dc9357SAndroid Build Coastguard Worker     case kpidHeadersSize: if (e) prop = (e->h.overHead << 9); break;
809*f6dc9357SAndroid Build Coastguard Worker     case kpidMethod:
810*f6dc9357SAndroid Build Coastguard Worker     {
811*f6dc9357SAndroid Build Coastguard Worker       AString s;
812*f6dc9357SAndroid Build Coastguard Worker 
813*f6dc9357SAndroid Build Coastguard Worker       if (desc && !desc->createType.IsEmpty())
814*f6dc9357SAndroid Build Coastguard Worker         s = desc->createType;
815*f6dc9357SAndroid Build Coastguard Worker 
816*f6dc9357SAndroid Build Coastguard Worker       bool zlib = false;
817*f6dc9357SAndroid Build Coastguard Worker       bool marker = false;
818*f6dc9357SAndroid Build Coastguard Worker       Int32 algo = -1;
819*f6dc9357SAndroid Build Coastguard Worker 
820*f6dc9357SAndroid Build Coastguard Worker       FOR_VECTOR (i, _extents)
821*f6dc9357SAndroid Build Coastguard Worker       {
822*f6dc9357SAndroid Build Coastguard Worker         const CExtent &extent = _extents[i];
823*f6dc9357SAndroid Build Coastguard Worker         if (!extent.IsOK || !extent.IsVmdk())
824*f6dc9357SAndroid Build Coastguard Worker           continue;
825*f6dc9357SAndroid Build Coastguard Worker 
826*f6dc9357SAndroid Build Coastguard Worker         const CHeader &h = extent.h;
827*f6dc9357SAndroid Build Coastguard Worker 
828*f6dc9357SAndroid Build Coastguard Worker         if (h.algo != 0)
829*f6dc9357SAndroid Build Coastguard Worker         {
830*f6dc9357SAndroid Build Coastguard Worker           if (h.algo == 1)
831*f6dc9357SAndroid Build Coastguard Worker             zlib = true;
832*f6dc9357SAndroid Build Coastguard Worker           else if (algo != h.algo)
833*f6dc9357SAndroid Build Coastguard Worker           {
834*f6dc9357SAndroid Build Coastguard Worker             s.Add_Space_if_NotEmpty();
835*f6dc9357SAndroid Build Coastguard Worker             s.Add_UInt32(h.algo);
836*f6dc9357SAndroid Build Coastguard Worker             algo = h.algo;
837*f6dc9357SAndroid Build Coastguard Worker           }
838*f6dc9357SAndroid Build Coastguard Worker         }
839*f6dc9357SAndroid Build Coastguard Worker 
840*f6dc9357SAndroid Build Coastguard Worker         if (h.Is_Marker())
841*f6dc9357SAndroid Build Coastguard Worker           marker = true;
842*f6dc9357SAndroid Build Coastguard Worker       }
843*f6dc9357SAndroid Build Coastguard Worker 
844*f6dc9357SAndroid Build Coastguard Worker       if (zlib)
845*f6dc9357SAndroid Build Coastguard Worker         s.Add_OptSpaced("zlib");
846*f6dc9357SAndroid Build Coastguard Worker 
847*f6dc9357SAndroid Build Coastguard Worker       if (marker)
848*f6dc9357SAndroid Build Coastguard Worker         s.Add_OptSpaced("Marker");
849*f6dc9357SAndroid Build Coastguard Worker 
850*f6dc9357SAndroid Build Coastguard Worker       if (!s.IsEmpty())
851*f6dc9357SAndroid Build Coastguard Worker         prop = s;
852*f6dc9357SAndroid Build Coastguard Worker       break;
853*f6dc9357SAndroid Build Coastguard Worker     }
854*f6dc9357SAndroid Build Coastguard Worker 
855*f6dc9357SAndroid Build Coastguard Worker     case kpidComment:
856*f6dc9357SAndroid Build Coastguard Worker     {
857*f6dc9357SAndroid Build Coastguard Worker       if (e && e->DescriptorBuf.Size() != 0)
858*f6dc9357SAndroid Build Coastguard Worker       {
859*f6dc9357SAndroid Build Coastguard Worker         AString s;
860*f6dc9357SAndroid Build Coastguard Worker         s.SetFrom_CalcLen((const char *)(const Byte *)e->DescriptorBuf, (unsigned)e->DescriptorBuf.Size());
861*f6dc9357SAndroid Build Coastguard Worker         if (!s.IsEmpty() && s.Len() <= (1 << 16))
862*f6dc9357SAndroid Build Coastguard Worker           prop = s;
863*f6dc9357SAndroid Build Coastguard Worker       }
864*f6dc9357SAndroid Build Coastguard Worker       break;
865*f6dc9357SAndroid Build Coastguard Worker     }
866*f6dc9357SAndroid Build Coastguard Worker 
867*f6dc9357SAndroid Build Coastguard Worker     case kpidId:
868*f6dc9357SAndroid Build Coastguard Worker     {
869*f6dc9357SAndroid Build Coastguard Worker       if (desc && !desc->CID.IsEmpty())
870*f6dc9357SAndroid Build Coastguard Worker       {
871*f6dc9357SAndroid Build Coastguard Worker         prop = desc->CID;
872*f6dc9357SAndroid Build Coastguard Worker       }
873*f6dc9357SAndroid Build Coastguard Worker       break;
874*f6dc9357SAndroid Build Coastguard Worker     }
875*f6dc9357SAndroid Build Coastguard Worker 
876*f6dc9357SAndroid Build Coastguard Worker     case kpidName:
877*f6dc9357SAndroid Build Coastguard Worker     {
878*f6dc9357SAndroid Build Coastguard Worker       if (!_isMultiVol && desc && desc->Extents.Size() == 1)
879*f6dc9357SAndroid Build Coastguard Worker       {
880*f6dc9357SAndroid Build Coastguard Worker         const CExtentInfo &ei = desc->Extents[0];
881*f6dc9357SAndroid Build Coastguard Worker         if (!ei.FileName.IsEmpty())
882*f6dc9357SAndroid Build Coastguard Worker         {
883*f6dc9357SAndroid Build Coastguard Worker           UString u;
884*f6dc9357SAndroid Build Coastguard Worker           CDescriptor::GetUnicodeName(ei.FileName, u);
885*f6dc9357SAndroid Build Coastguard Worker           if (!u.IsEmpty())
886*f6dc9357SAndroid Build Coastguard Worker             prop = u;
887*f6dc9357SAndroid Build Coastguard Worker         }
888*f6dc9357SAndroid Build Coastguard Worker       }
889*f6dc9357SAndroid Build Coastguard Worker       break;
890*f6dc9357SAndroid Build Coastguard Worker     }
891*f6dc9357SAndroid Build Coastguard Worker 
892*f6dc9357SAndroid Build Coastguard Worker     case kpidNumVolumes: if (_isMultiVol) prop = (UInt32)_extents.Size(); break;
893*f6dc9357SAndroid Build Coastguard Worker 
894*f6dc9357SAndroid Build Coastguard Worker     case kpidError:
895*f6dc9357SAndroid Build Coastguard Worker     {
896*f6dc9357SAndroid Build Coastguard Worker       if (_missingVol || !_missingVolName.IsEmpty())
897*f6dc9357SAndroid Build Coastguard Worker       {
898*f6dc9357SAndroid Build Coastguard Worker         UString s ("Missing volume : ");
899*f6dc9357SAndroid Build Coastguard Worker         if (!_missingVolName.IsEmpty())
900*f6dc9357SAndroid Build Coastguard Worker           s += _missingVolName;
901*f6dc9357SAndroid Build Coastguard Worker         prop = s;
902*f6dc9357SAndroid Build Coastguard Worker       }
903*f6dc9357SAndroid Build Coastguard Worker       break;
904*f6dc9357SAndroid Build Coastguard Worker     }
905*f6dc9357SAndroid Build Coastguard Worker 
906*f6dc9357SAndroid Build Coastguard Worker     case kpidErrorFlags:
907*f6dc9357SAndroid Build Coastguard Worker     {
908*f6dc9357SAndroid Build Coastguard Worker       UInt32 v = 0;
909*f6dc9357SAndroid Build Coastguard Worker       if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;
910*f6dc9357SAndroid Build Coastguard Worker       if (_unsupported) v |= kpv_ErrorFlags_UnsupportedMethod;
911*f6dc9357SAndroid Build Coastguard Worker       if (_unsupportedSome) v |= kpv_ErrorFlags_UnsupportedMethod;
912*f6dc9357SAndroid Build Coastguard Worker       if (_headerError) v |= kpv_ErrorFlags_HeadersError;
913*f6dc9357SAndroid Build Coastguard Worker       // if (_missingVol)  v |= kpv_ErrorFlags_UnexpectedEnd;
914*f6dc9357SAndroid Build Coastguard Worker       if (v != 0)
915*f6dc9357SAndroid Build Coastguard Worker         prop = v;
916*f6dc9357SAndroid Build Coastguard Worker       break;
917*f6dc9357SAndroid Build Coastguard Worker     }
918*f6dc9357SAndroid Build Coastguard Worker   }
919*f6dc9357SAndroid Build Coastguard Worker 
920*f6dc9357SAndroid Build Coastguard Worker   prop.Detach(value);
921*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
922*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_END
923*f6dc9357SAndroid Build Coastguard Worker }
924*f6dc9357SAndroid Build Coastguard Worker 
925*f6dc9357SAndroid Build Coastguard Worker 
926*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value))
927*f6dc9357SAndroid Build Coastguard Worker {
928*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_BEGIN
929*f6dc9357SAndroid Build Coastguard Worker   NCOM::CPropVariant prop;
930*f6dc9357SAndroid Build Coastguard Worker 
931*f6dc9357SAndroid Build Coastguard Worker   switch (propID)
932*f6dc9357SAndroid Build Coastguard Worker   {
933*f6dc9357SAndroid Build Coastguard Worker     case kpidSize: prop = _size; break;
934*f6dc9357SAndroid Build Coastguard Worker     case kpidPackSize:
935*f6dc9357SAndroid Build Coastguard Worker     {
936*f6dc9357SAndroid Build Coastguard Worker       UInt64 packSize = 0;
937*f6dc9357SAndroid Build Coastguard Worker       FOR_VECTOR (i, _extents)
938*f6dc9357SAndroid Build Coastguard Worker       {
939*f6dc9357SAndroid Build Coastguard Worker         const CExtent &e = _extents[i];
940*f6dc9357SAndroid Build Coastguard Worker         if (!e.IsOK)
941*f6dc9357SAndroid Build Coastguard Worker           continue;
942*f6dc9357SAndroid Build Coastguard Worker         if (e.IsVmdk() && !_isMultiVol)
943*f6dc9357SAndroid Build Coastguard Worker         {
944*f6dc9357SAndroid Build Coastguard Worker           UInt64 ov = (e.h.overHead << 9);
945*f6dc9357SAndroid Build Coastguard Worker           if (e.PhySize >= ov)
946*f6dc9357SAndroid Build Coastguard Worker             packSize += e.PhySize - ov;
947*f6dc9357SAndroid Build Coastguard Worker         }
948*f6dc9357SAndroid Build Coastguard Worker         else
949*f6dc9357SAndroid Build Coastguard Worker           packSize += e.PhySize;
950*f6dc9357SAndroid Build Coastguard Worker       }
951*f6dc9357SAndroid Build Coastguard Worker       prop = packSize;
952*f6dc9357SAndroid Build Coastguard Worker       break;
953*f6dc9357SAndroid Build Coastguard Worker     }
954*f6dc9357SAndroid Build Coastguard Worker     case kpidExtension: prop = (_imgExt ? _imgExt : "img"); break;
955*f6dc9357SAndroid Build Coastguard Worker   }
956*f6dc9357SAndroid Build Coastguard Worker 
957*f6dc9357SAndroid Build Coastguard Worker   prop.Detach(value);
958*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
959*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_END
960*f6dc9357SAndroid Build Coastguard Worker }
961*f6dc9357SAndroid Build Coastguard Worker 
962*f6dc9357SAndroid Build Coastguard Worker 
963*f6dc9357SAndroid Build Coastguard Worker static int inline GetLog(UInt64 num)
964*f6dc9357SAndroid Build Coastguard Worker {
965*f6dc9357SAndroid Build Coastguard Worker   for (int i = 0; i < 64; i++)
966*f6dc9357SAndroid Build Coastguard Worker     if (((UInt64)1 << i) == num)
967*f6dc9357SAndroid Build Coastguard Worker       return i;
968*f6dc9357SAndroid Build Coastguard Worker   return -1;
969*f6dc9357SAndroid Build Coastguard Worker }
970*f6dc9357SAndroid Build Coastguard Worker 
971*f6dc9357SAndroid Build Coastguard Worker 
972*f6dc9357SAndroid Build Coastguard Worker HRESULT CExtent::ReadForHeader(IInStream *stream, UInt64 sector, void *data, size_t numSectors)
973*f6dc9357SAndroid Build Coastguard Worker {
974*f6dc9357SAndroid Build Coastguard Worker   sector <<= 9;
975*f6dc9357SAndroid Build Coastguard Worker   RINOK(InStream_SeekSet(stream, sector))
976*f6dc9357SAndroid Build Coastguard Worker   size_t size = numSectors << 9;
977*f6dc9357SAndroid Build Coastguard Worker   RINOK(ReadStream_FALSE(stream, data, size))
978*f6dc9357SAndroid Build Coastguard Worker   UInt64 end = sector + size;
979*f6dc9357SAndroid Build Coastguard Worker   if (PhySize < end)
980*f6dc9357SAndroid Build Coastguard Worker     PhySize = end;
981*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
982*f6dc9357SAndroid Build Coastguard Worker }
983*f6dc9357SAndroid Build Coastguard Worker 
984*f6dc9357SAndroid Build Coastguard Worker 
985*f6dc9357SAndroid Build Coastguard Worker void CHandler::CloseAtError()
986*f6dc9357SAndroid Build Coastguard Worker {
987*f6dc9357SAndroid Build Coastguard Worker   _extents.Clear();
988*f6dc9357SAndroid Build Coastguard Worker   CHandlerImg::CloseAtError();
989*f6dc9357SAndroid Build Coastguard Worker }
990*f6dc9357SAndroid Build Coastguard Worker 
991*f6dc9357SAndroid Build Coastguard Worker 
992*f6dc9357SAndroid Build Coastguard Worker static const char * const kSignature_Descriptor = "# Disk DescriptorFile";
993*f6dc9357SAndroid Build Coastguard Worker 
994*f6dc9357SAndroid Build Coastguard Worker 
995*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback)
996*f6dc9357SAndroid Build Coastguard Worker {
997*f6dc9357SAndroid Build Coastguard Worker   const unsigned kSectoreSize = 512;
998*f6dc9357SAndroid Build Coastguard Worker   Byte buf[kSectoreSize];
999*f6dc9357SAndroid Build Coastguard Worker   size_t headerSize = kSectoreSize;
1000*f6dc9357SAndroid Build Coastguard Worker   RINOK(ReadStream(stream, buf, &headerSize))
1001*f6dc9357SAndroid Build Coastguard Worker 
1002*f6dc9357SAndroid Build Coastguard Worker   if (headerSize < sizeof(k_Signature))
1003*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
1004*f6dc9357SAndroid Build Coastguard Worker 
1005*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<IArchiveOpenVolumeCallback> volumeCallback;
1006*f6dc9357SAndroid Build Coastguard Worker 
1007*f6dc9357SAndroid Build Coastguard Worker   if (memcmp(buf, k_Signature, sizeof(k_Signature)) != 0)
1008*f6dc9357SAndroid Build Coastguard Worker   {
1009*f6dc9357SAndroid Build Coastguard Worker     const size_t k_SigDesc_Size = strlen(kSignature_Descriptor);
1010*f6dc9357SAndroid Build Coastguard Worker     if (headerSize < k_SigDesc_Size)
1011*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
1012*f6dc9357SAndroid Build Coastguard Worker     if (memcmp(buf, kSignature_Descriptor, k_SigDesc_Size) != 0)
1013*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
1014*f6dc9357SAndroid Build Coastguard Worker 
1015*f6dc9357SAndroid Build Coastguard Worker     UInt64 endPos;
1016*f6dc9357SAndroid Build Coastguard Worker     RINOK(InStream_GetSize_SeekToEnd(stream, endPos))
1017*f6dc9357SAndroid Build Coastguard Worker     if (endPos > (1 << 20))
1018*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
1019*f6dc9357SAndroid Build Coastguard Worker     const size_t numBytes = (size_t)endPos;
1020*f6dc9357SAndroid Build Coastguard Worker     _descriptorBuf.Alloc(numBytes);
1021*f6dc9357SAndroid Build Coastguard Worker     RINOK(InStream_SeekToBegin(stream))
1022*f6dc9357SAndroid Build Coastguard Worker     RINOK(ReadStream_FALSE(stream, _descriptorBuf, numBytes))
1023*f6dc9357SAndroid Build Coastguard Worker 
1024*f6dc9357SAndroid Build Coastguard Worker     if (!_descriptor.Parse(_descriptorBuf, _descriptorBuf.Size()))
1025*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
1026*f6dc9357SAndroid Build Coastguard Worker     _isMultiVol = true;
1027*f6dc9357SAndroid Build Coastguard Worker     _isArc = true;
1028*f6dc9357SAndroid Build Coastguard Worker     _phySize = numBytes;
1029*f6dc9357SAndroid Build Coastguard Worker     if (_descriptor.IsThere_Parent())
1030*f6dc9357SAndroid Build Coastguard Worker       _unsupported = true;
1031*f6dc9357SAndroid Build Coastguard Worker 
1032*f6dc9357SAndroid Build Coastguard Worker     if (openCallback)
1033*f6dc9357SAndroid Build Coastguard Worker     {
1034*f6dc9357SAndroid Build Coastguard Worker       openCallback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&volumeCallback);
1035*f6dc9357SAndroid Build Coastguard Worker     }
1036*f6dc9357SAndroid Build Coastguard Worker     if (!volumeCallback)
1037*f6dc9357SAndroid Build Coastguard Worker     {
1038*f6dc9357SAndroid Build Coastguard Worker       _unsupported = true;
1039*f6dc9357SAndroid Build Coastguard Worker       return E_NOTIMPL;
1040*f6dc9357SAndroid Build Coastguard Worker     }
1041*f6dc9357SAndroid Build Coastguard Worker 
1042*f6dc9357SAndroid Build Coastguard Worker     /*
1043*f6dc9357SAndroid Build Coastguard Worker     UInt64 totalVirtSize = 0;
1044*f6dc9357SAndroid Build Coastguard Worker     FOR_VECTOR (i, _descriptor.Extents)
1045*f6dc9357SAndroid Build Coastguard Worker     {
1046*f6dc9357SAndroid Build Coastguard Worker       const CExtentInfo &ei = _descriptor.Extents[i];
1047*f6dc9357SAndroid Build Coastguard Worker       if (ei.NumSectors >= ((UInt64)1 << (63 - 9)))
1048*f6dc9357SAndroid Build Coastguard Worker         return S_FALSE;
1049*f6dc9357SAndroid Build Coastguard Worker       totalVirtSize += ei.NumSectors;
1050*f6dc9357SAndroid Build Coastguard Worker       if (totalVirtSize >= ((UInt64)1 << (63 - 9)))
1051*f6dc9357SAndroid Build Coastguard Worker         return S_FALSE;
1052*f6dc9357SAndroid Build Coastguard Worker     }
1053*f6dc9357SAndroid Build Coastguard Worker     totalVirtSize <<= 9;
1054*f6dc9357SAndroid Build Coastguard Worker     */
1055*f6dc9357SAndroid Build Coastguard Worker 
1056*f6dc9357SAndroid Build Coastguard Worker     if (_descriptor.Extents.Size() > 1)
1057*f6dc9357SAndroid Build Coastguard Worker     {
1058*f6dc9357SAndroid Build Coastguard Worker       const UInt64 numFiles = _descriptor.Extents.Size();
1059*f6dc9357SAndroid Build Coastguard Worker       RINOK(openCallback->SetTotal(&numFiles, NULL))
1060*f6dc9357SAndroid Build Coastguard Worker     }
1061*f6dc9357SAndroid Build Coastguard Worker   }
1062*f6dc9357SAndroid Build Coastguard Worker 
1063*f6dc9357SAndroid Build Coastguard Worker   UInt64 complexity = 0;
1064*f6dc9357SAndroid Build Coastguard Worker 
1065*f6dc9357SAndroid Build Coastguard Worker   for (;;)
1066*f6dc9357SAndroid Build Coastguard Worker   {
1067*f6dc9357SAndroid Build Coastguard Worker     CExtent *e = NULL;
1068*f6dc9357SAndroid Build Coastguard Worker     CMyComPtr<IInStream> nextStream;
1069*f6dc9357SAndroid Build Coastguard Worker 
1070*f6dc9357SAndroid Build Coastguard Worker     if (_isMultiVol)
1071*f6dc9357SAndroid Build Coastguard Worker     {
1072*f6dc9357SAndroid Build Coastguard Worker       const unsigned extentIndex = _extents.Size();
1073*f6dc9357SAndroid Build Coastguard Worker       if (extentIndex >= _descriptor.Extents.Size())
1074*f6dc9357SAndroid Build Coastguard Worker         break;
1075*f6dc9357SAndroid Build Coastguard Worker       const CExtentInfo &ei = _descriptor.Extents[extentIndex];
1076*f6dc9357SAndroid Build Coastguard Worker       e = &_extents.AddNew();
1077*f6dc9357SAndroid Build Coastguard Worker       e->StartOffset = 0;
1078*f6dc9357SAndroid Build Coastguard Worker       if (ei.NumSectors >= ((UInt64)1 << (62 - 9)) ||
1079*f6dc9357SAndroid Build Coastguard Worker           ei.StartSector >= ((UInt64)1 << (62 - 9)))
1080*f6dc9357SAndroid Build Coastguard Worker         return S_FALSE;
1081*f6dc9357SAndroid Build Coastguard Worker       e->NumBytes = ei.NumSectors << 9;
1082*f6dc9357SAndroid Build Coastguard Worker       e->IsZero = ei.IsType_ZERO();
1083*f6dc9357SAndroid Build Coastguard Worker       if (extentIndex != 0)
1084*f6dc9357SAndroid Build Coastguard Worker         e->StartOffset = _extents[extentIndex - 1].GetEndOffset();
1085*f6dc9357SAndroid Build Coastguard Worker       if (e->GetEndOffset() < e->StartOffset)
1086*f6dc9357SAndroid Build Coastguard Worker         return S_FALSE;
1087*f6dc9357SAndroid Build Coastguard Worker 
1088*f6dc9357SAndroid Build Coastguard Worker       e->VirtSize = e->NumBytes;
1089*f6dc9357SAndroid Build Coastguard Worker       if (e->IsZero)
1090*f6dc9357SAndroid Build Coastguard Worker       {
1091*f6dc9357SAndroid Build Coastguard Worker         e->IsOK = true;
1092*f6dc9357SAndroid Build Coastguard Worker         continue;
1093*f6dc9357SAndroid Build Coastguard Worker       }
1094*f6dc9357SAndroid Build Coastguard Worker 
1095*f6dc9357SAndroid Build Coastguard Worker       e->IsFlat = ei.IsType_Flat();
1096*f6dc9357SAndroid Build Coastguard Worker       e->FlatOffset = ei.StartSector << 9;
1097*f6dc9357SAndroid Build Coastguard Worker 
1098*f6dc9357SAndroid Build Coastguard Worker       UString u;
1099*f6dc9357SAndroid Build Coastguard Worker       CDescriptor::GetUnicodeName(ei.FileName, u);
1100*f6dc9357SAndroid Build Coastguard Worker       if (u.IsEmpty())
1101*f6dc9357SAndroid Build Coastguard Worker       {
1102*f6dc9357SAndroid Build Coastguard Worker         _missingVol = true;
1103*f6dc9357SAndroid Build Coastguard Worker         continue;
1104*f6dc9357SAndroid Build Coastguard Worker       }
1105*f6dc9357SAndroid Build Coastguard Worker 
1106*f6dc9357SAndroid Build Coastguard Worker       HRESULT result = volumeCallback->GetStream(u, &nextStream);
1107*f6dc9357SAndroid Build Coastguard Worker 
1108*f6dc9357SAndroid Build Coastguard Worker       if (result != S_OK && result != S_FALSE)
1109*f6dc9357SAndroid Build Coastguard Worker         return result;
1110*f6dc9357SAndroid Build Coastguard Worker 
1111*f6dc9357SAndroid Build Coastguard Worker       if (!nextStream || result != S_OK)
1112*f6dc9357SAndroid Build Coastguard Worker       {
1113*f6dc9357SAndroid Build Coastguard Worker         if (_missingVolName.IsEmpty())
1114*f6dc9357SAndroid Build Coastguard Worker           _missingVolName = u;
1115*f6dc9357SAndroid Build Coastguard Worker         _missingVol = true;
1116*f6dc9357SAndroid Build Coastguard Worker         continue;
1117*f6dc9357SAndroid Build Coastguard Worker       }
1118*f6dc9357SAndroid Build Coastguard Worker 
1119*f6dc9357SAndroid Build Coastguard Worker       if (e->IsFlat)
1120*f6dc9357SAndroid Build Coastguard Worker       {
1121*f6dc9357SAndroid Build Coastguard Worker         e->IsOK = true;
1122*f6dc9357SAndroid Build Coastguard Worker         e->Stream = nextStream;
1123*f6dc9357SAndroid Build Coastguard Worker         e->PhySize = e->NumBytes;
1124*f6dc9357SAndroid Build Coastguard Worker         continue;
1125*f6dc9357SAndroid Build Coastguard Worker       }
1126*f6dc9357SAndroid Build Coastguard Worker 
1127*f6dc9357SAndroid Build Coastguard Worker       stream = nextStream;
1128*f6dc9357SAndroid Build Coastguard Worker 
1129*f6dc9357SAndroid Build Coastguard Worker       headerSize = kSectoreSize;
1130*f6dc9357SAndroid Build Coastguard Worker       RINOK(ReadStream(stream, buf, &headerSize))
1131*f6dc9357SAndroid Build Coastguard Worker 
1132*f6dc9357SAndroid Build Coastguard Worker       if (headerSize != kSectoreSize)
1133*f6dc9357SAndroid Build Coastguard Worker         continue;
1134*f6dc9357SAndroid Build Coastguard Worker       if (memcmp(buf, k_Signature, sizeof(k_Signature)) != 0)
1135*f6dc9357SAndroid Build Coastguard Worker         continue;
1136*f6dc9357SAndroid Build Coastguard Worker     }
1137*f6dc9357SAndroid Build Coastguard Worker     else
1138*f6dc9357SAndroid Build Coastguard Worker     {
1139*f6dc9357SAndroid Build Coastguard Worker       if (headerSize != kSectoreSize)
1140*f6dc9357SAndroid Build Coastguard Worker         return S_FALSE;
1141*f6dc9357SAndroid Build Coastguard Worker       e = &_extents.AddNew();
1142*f6dc9357SAndroid Build Coastguard Worker       e->StartOffset = 0;
1143*f6dc9357SAndroid Build Coastguard Worker     }
1144*f6dc9357SAndroid Build Coastguard Worker 
1145*f6dc9357SAndroid Build Coastguard Worker     HRESULT res = S_FALSE;
1146*f6dc9357SAndroid Build Coastguard Worker     if (e->h.Parse(buf))
1147*f6dc9357SAndroid Build Coastguard Worker       res = e->Open3(stream, openCallback, _isMultiVol ? _descriptor.Extents.Size() : 1, _extents.Size() - 1, complexity);
1148*f6dc9357SAndroid Build Coastguard Worker 
1149*f6dc9357SAndroid Build Coastguard Worker     if (!_isMultiVol)
1150*f6dc9357SAndroid Build Coastguard Worker     {
1151*f6dc9357SAndroid Build Coastguard Worker       _isArc = e->IsArc;
1152*f6dc9357SAndroid Build Coastguard Worker       _phySize = e->PhySize;
1153*f6dc9357SAndroid Build Coastguard Worker       _unsupported = e->Unsupported;
1154*f6dc9357SAndroid Build Coastguard Worker     }
1155*f6dc9357SAndroid Build Coastguard Worker 
1156*f6dc9357SAndroid Build Coastguard Worker     if (e->Unsupported)
1157*f6dc9357SAndroid Build Coastguard Worker       _unsupportedSome = true;
1158*f6dc9357SAndroid Build Coastguard Worker     if (e->HeadersError)
1159*f6dc9357SAndroid Build Coastguard Worker       _headerError = true;
1160*f6dc9357SAndroid Build Coastguard Worker 
1161*f6dc9357SAndroid Build Coastguard Worker     if (res != S_OK)
1162*f6dc9357SAndroid Build Coastguard Worker     {
1163*f6dc9357SAndroid Build Coastguard Worker       if (res != S_FALSE)
1164*f6dc9357SAndroid Build Coastguard Worker         return res;
1165*f6dc9357SAndroid Build Coastguard Worker       if (!_isMultiVol)
1166*f6dc9357SAndroid Build Coastguard Worker         return res;
1167*f6dc9357SAndroid Build Coastguard Worker       continue;
1168*f6dc9357SAndroid Build Coastguard Worker     }
1169*f6dc9357SAndroid Build Coastguard Worker 
1170*f6dc9357SAndroid Build Coastguard Worker     e->Stream = stream;
1171*f6dc9357SAndroid Build Coastguard Worker     e->IsOK = true;
1172*f6dc9357SAndroid Build Coastguard Worker 
1173*f6dc9357SAndroid Build Coastguard Worker     if (!_isMultiVol)
1174*f6dc9357SAndroid Build Coastguard Worker     {
1175*f6dc9357SAndroid Build Coastguard Worker       e->NumBytes = e->VirtSize;
1176*f6dc9357SAndroid Build Coastguard Worker       break;
1177*f6dc9357SAndroid Build Coastguard Worker     }
1178*f6dc9357SAndroid Build Coastguard Worker 
1179*f6dc9357SAndroid Build Coastguard Worker     if (e->NumBytes != e->VirtSize)
1180*f6dc9357SAndroid Build Coastguard Worker       _headerError = true;
1181*f6dc9357SAndroid Build Coastguard Worker   }
1182*f6dc9357SAndroid Build Coastguard Worker 
1183*f6dc9357SAndroid Build Coastguard Worker   if (!_extents.IsEmpty())
1184*f6dc9357SAndroid Build Coastguard Worker     _size = _extents.Back().GetEndOffset();
1185*f6dc9357SAndroid Build Coastguard Worker 
1186*f6dc9357SAndroid Build Coastguard Worker   _needDeflate = false;
1187*f6dc9357SAndroid Build Coastguard Worker   _clusterBitsMax = 0;
1188*f6dc9357SAndroid Build Coastguard Worker 
1189*f6dc9357SAndroid Build Coastguard Worker   // unsigned numOKs = 0;
1190*f6dc9357SAndroid Build Coastguard Worker   unsigned numUnsupported = 0;
1191*f6dc9357SAndroid Build Coastguard Worker 
1192*f6dc9357SAndroid Build Coastguard Worker   FOR_VECTOR (i, _extents)
1193*f6dc9357SAndroid Build Coastguard Worker   {
1194*f6dc9357SAndroid Build Coastguard Worker     const CExtent &e = _extents[i];
1195*f6dc9357SAndroid Build Coastguard Worker     if (e.Unsupported)
1196*f6dc9357SAndroid Build Coastguard Worker       numUnsupported++;
1197*f6dc9357SAndroid Build Coastguard Worker     if (!e.IsOK)
1198*f6dc9357SAndroid Build Coastguard Worker       continue;
1199*f6dc9357SAndroid Build Coastguard Worker     // numOKs++;
1200*f6dc9357SAndroid Build Coastguard Worker     if (e.IsVmdk())
1201*f6dc9357SAndroid Build Coastguard Worker     {
1202*f6dc9357SAndroid Build Coastguard Worker       if (e.NeedDeflate)
1203*f6dc9357SAndroid Build Coastguard Worker         _needDeflate = true;
1204*f6dc9357SAndroid Build Coastguard Worker       if (_clusterBitsMax < e.ClusterBits)
1205*f6dc9357SAndroid Build Coastguard Worker         _clusterBitsMax = e.ClusterBits;
1206*f6dc9357SAndroid Build Coastguard Worker     }
1207*f6dc9357SAndroid Build Coastguard Worker   }
1208*f6dc9357SAndroid Build Coastguard Worker 
1209*f6dc9357SAndroid Build Coastguard Worker   if (numUnsupported != 0 && numUnsupported == _extents.Size())
1210*f6dc9357SAndroid Build Coastguard Worker     _unsupported = true;
1211*f6dc9357SAndroid Build Coastguard Worker 
1212*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
1213*f6dc9357SAndroid Build Coastguard Worker }
1214*f6dc9357SAndroid Build Coastguard Worker 
1215*f6dc9357SAndroid Build Coastguard Worker 
1216*f6dc9357SAndroid Build Coastguard Worker HRESULT CExtent::Open3(IInStream *stream, IArchiveOpenCallback *openCallback,
1217*f6dc9357SAndroid Build Coastguard Worker     unsigned numVols, unsigned volIndex, UInt64 &complexity)
1218*f6dc9357SAndroid Build Coastguard Worker {
1219*f6dc9357SAndroid Build Coastguard Worker   if (h.descriptorSize != 0)
1220*f6dc9357SAndroid Build Coastguard Worker   {
1221*f6dc9357SAndroid Build Coastguard Worker     if (h.descriptorOffset == 0 ||
1222*f6dc9357SAndroid Build Coastguard Worker         h.descriptorSize > (1 << 10))
1223*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
1224*f6dc9357SAndroid Build Coastguard Worker     DescriptorBuf.Alloc((size_t)h.descriptorSize << 9);
1225*f6dc9357SAndroid Build Coastguard Worker     RINOK(ReadForHeader(stream, h.descriptorOffset, DescriptorBuf, (size_t)h.descriptorSize))
1226*f6dc9357SAndroid Build Coastguard Worker     if (h.descriptorOffset == 1 && h.Is_Marker() && Get64(DescriptorBuf) == 0)
1227*f6dc9357SAndroid Build Coastguard Worker     {
1228*f6dc9357SAndroid Build Coastguard Worker       // We check data as end marker.
1229*f6dc9357SAndroid Build Coastguard Worker       // and if probably it's footer's copy of header, we don't want to open it.
1230*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
1231*f6dc9357SAndroid Build Coastguard Worker     }
1232*f6dc9357SAndroid Build Coastguard Worker 
1233*f6dc9357SAndroid Build Coastguard Worker     DescriptorOK = Descriptor.Parse(DescriptorBuf, DescriptorBuf.Size());
1234*f6dc9357SAndroid Build Coastguard Worker     if (!DescriptorOK)
1235*f6dc9357SAndroid Build Coastguard Worker       HeadersError = true;
1236*f6dc9357SAndroid Build Coastguard Worker     if (Descriptor.IsThere_Parent())
1237*f6dc9357SAndroid Build Coastguard Worker       Unsupported = true;
1238*f6dc9357SAndroid Build Coastguard Worker   }
1239*f6dc9357SAndroid Build Coastguard Worker 
1240*f6dc9357SAndroid Build Coastguard Worker   if (h.gdOffset == (UInt64)(Int64)-1)
1241*f6dc9357SAndroid Build Coastguard Worker   {
1242*f6dc9357SAndroid Build Coastguard Worker     // Grain Dir is at end of file
1243*f6dc9357SAndroid Build Coastguard Worker     UInt64 endPos;
1244*f6dc9357SAndroid Build Coastguard Worker     RINOK(InStream_GetSize_SeekToEnd(stream, endPos))
1245*f6dc9357SAndroid Build Coastguard Worker     if ((endPos & 511) != 0)
1246*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
1247*f6dc9357SAndroid Build Coastguard Worker 
1248*f6dc9357SAndroid Build Coastguard Worker     const size_t kEndSize = 512 * 3;
1249*f6dc9357SAndroid Build Coastguard Worker     Byte buf2[kEndSize];
1250*f6dc9357SAndroid Build Coastguard Worker     if (endPos < kEndSize)
1251*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
1252*f6dc9357SAndroid Build Coastguard Worker     RINOK(InStream_SeekSet(stream, endPos - kEndSize))
1253*f6dc9357SAndroid Build Coastguard Worker     RINOK(ReadStream_FALSE(stream, buf2, kEndSize))
1254*f6dc9357SAndroid Build Coastguard Worker 
1255*f6dc9357SAndroid Build Coastguard Worker     CHeader h2;
1256*f6dc9357SAndroid Build Coastguard Worker     if (!h2.Parse(buf2 + 512))
1257*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
1258*f6dc9357SAndroid Build Coastguard Worker     if (!h.IsSameImageFor(h2))
1259*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
1260*f6dc9357SAndroid Build Coastguard Worker 
1261*f6dc9357SAndroid Build Coastguard Worker     h = h2;
1262*f6dc9357SAndroid Build Coastguard Worker 
1263*f6dc9357SAndroid Build Coastguard Worker     CMarker m;
1264*f6dc9357SAndroid Build Coastguard Worker     m.Parse(buf2);
1265*f6dc9357SAndroid Build Coastguard Worker     if (m.NumSectors != 1 || m.SpecSize != 0 || m.Type != k_Marker_FOOTER)
1266*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
1267*f6dc9357SAndroid Build Coastguard Worker     m.Parse(buf2 + 512 * 2);
1268*f6dc9357SAndroid Build Coastguard Worker     if (m.NumSectors != 0 || m.SpecSize != 0 || m.Type != k_Marker_END_OF_STREAM)
1269*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
1270*f6dc9357SAndroid Build Coastguard Worker     PhySize = endPos;
1271*f6dc9357SAndroid Build Coastguard Worker   }
1272*f6dc9357SAndroid Build Coastguard Worker 
1273*f6dc9357SAndroid Build Coastguard Worker   const int grainSize_Log = GetLog(h.grainSize);
1274*f6dc9357SAndroid Build Coastguard Worker   if (grainSize_Log < 3 || grainSize_Log > 30 - 9) // grain size must be >= 4 KB
1275*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
1276*f6dc9357SAndroid Build Coastguard Worker   if (h.capacity >= ((UInt64)1 << (63 - 9)))
1277*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
1278*f6dc9357SAndroid Build Coastguard Worker   if (h.overHead >= ((UInt64)1 << (63 - 9)))
1279*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
1280*f6dc9357SAndroid Build Coastguard Worker 
1281*f6dc9357SAndroid Build Coastguard Worker   IsArc = true;
1282*f6dc9357SAndroid Build Coastguard Worker   ClusterBits = (9 + (unsigned)grainSize_Log);
1283*f6dc9357SAndroid Build Coastguard Worker   VirtSize = h.capacity << 9;
1284*f6dc9357SAndroid Build Coastguard Worker   NeedDeflate = (h.algo >= 1);
1285*f6dc9357SAndroid Build Coastguard Worker 
1286*f6dc9357SAndroid Build Coastguard Worker   if (h.Is_Compressed() ? (h.algo > 1 || !h.Is_Marker()) : (h.algo != 0))
1287*f6dc9357SAndroid Build Coastguard Worker   {
1288*f6dc9357SAndroid Build Coastguard Worker     Unsupported = true;
1289*f6dc9357SAndroid Build Coastguard Worker     PhySize = 0;
1290*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
1291*f6dc9357SAndroid Build Coastguard Worker   }
1292*f6dc9357SAndroid Build Coastguard Worker 
1293*f6dc9357SAndroid Build Coastguard Worker   {
1294*f6dc9357SAndroid Build Coastguard Worker     const UInt64 overHeadBytes = h.overHead << 9;
1295*f6dc9357SAndroid Build Coastguard Worker     if (PhySize < overHeadBytes)
1296*f6dc9357SAndroid Build Coastguard Worker       PhySize = overHeadBytes;
1297*f6dc9357SAndroid Build Coastguard Worker   }
1298*f6dc9357SAndroid Build Coastguard Worker 
1299*f6dc9357SAndroid Build Coastguard Worker   ZeroSector = 0;
1300*f6dc9357SAndroid Build Coastguard Worker   if (h.Is_ZeroGrain())
1301*f6dc9357SAndroid Build Coastguard Worker     ZeroSector = 1;
1302*f6dc9357SAndroid Build Coastguard Worker 
1303*f6dc9357SAndroid Build Coastguard Worker   const UInt64 numSectorsPerGde = (UInt64)1 << ((unsigned)grainSize_Log + k_NumMidBits);
1304*f6dc9357SAndroid Build Coastguard Worker   const UInt64 numGdeEntries = (h.capacity + numSectorsPerGde - 1) >> ((unsigned)grainSize_Log + k_NumMidBits);
1305*f6dc9357SAndroid Build Coastguard Worker   CByteBuffer table;
1306*f6dc9357SAndroid Build Coastguard Worker 
1307*f6dc9357SAndroid Build Coastguard Worker   if (numGdeEntries != 0)
1308*f6dc9357SAndroid Build Coastguard Worker   {
1309*f6dc9357SAndroid Build Coastguard Worker     if (h.gdOffset == 0)
1310*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
1311*f6dc9357SAndroid Build Coastguard Worker 
1312*f6dc9357SAndroid Build Coastguard Worker     size_t numSectors = (size_t)((numGdeEntries + ((1 << (9 - 2)) - 1)) >> (9 - 2));
1313*f6dc9357SAndroid Build Coastguard Worker     size_t t1SizeBytes = numSectors << 9;
1314*f6dc9357SAndroid Build Coastguard Worker     if ((t1SizeBytes >> 2) < numGdeEntries)
1315*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
1316*f6dc9357SAndroid Build Coastguard Worker     table.Alloc(t1SizeBytes);
1317*f6dc9357SAndroid Build Coastguard Worker 
1318*f6dc9357SAndroid Build Coastguard Worker     if (h.Is_Marker())
1319*f6dc9357SAndroid Build Coastguard Worker     {
1320*f6dc9357SAndroid Build Coastguard Worker       Byte buf2[1 << 9];
1321*f6dc9357SAndroid Build Coastguard Worker       if (ReadForHeader(stream, h.gdOffset - 1, buf2, 1) != S_OK)
1322*f6dc9357SAndroid Build Coastguard Worker         return S_FALSE;
1323*f6dc9357SAndroid Build Coastguard Worker       {
1324*f6dc9357SAndroid Build Coastguard Worker         CMarker m;
1325*f6dc9357SAndroid Build Coastguard Worker         m.Parse(buf2);
1326*f6dc9357SAndroid Build Coastguard Worker         if (m.Type != k_Marker_GRAIN_DIR
1327*f6dc9357SAndroid Build Coastguard Worker             || m.NumSectors != numSectors
1328*f6dc9357SAndroid Build Coastguard Worker             || m.SpecSize != 0)
1329*f6dc9357SAndroid Build Coastguard Worker           return S_FALSE;
1330*f6dc9357SAndroid Build Coastguard Worker       }
1331*f6dc9357SAndroid Build Coastguard Worker     }
1332*f6dc9357SAndroid Build Coastguard Worker 
1333*f6dc9357SAndroid Build Coastguard Worker     RINOK(ReadForHeader(stream, h.gdOffset, table, numSectors))
1334*f6dc9357SAndroid Build Coastguard Worker   }
1335*f6dc9357SAndroid Build Coastguard Worker 
1336*f6dc9357SAndroid Build Coastguard Worker   const size_t clusterSize = (size_t)1 << ClusterBits;
1337*f6dc9357SAndroid Build Coastguard Worker 
1338*f6dc9357SAndroid Build Coastguard Worker   const UInt64 complexityStart = complexity;
1339*f6dc9357SAndroid Build Coastguard Worker 
1340*f6dc9357SAndroid Build Coastguard Worker   if (openCallback)
1341*f6dc9357SAndroid Build Coastguard Worker   {
1342*f6dc9357SAndroid Build Coastguard Worker     complexity += (UInt64)numGdeEntries << (k_NumMidBits + 2);
1343*f6dc9357SAndroid Build Coastguard Worker     {
1344*f6dc9357SAndroid Build Coastguard Worker       const UInt64 numVols2 = numVols;
1345*f6dc9357SAndroid Build Coastguard Worker       RINOK(openCallback->SetTotal((numVols == 1) ? NULL : &numVols2, &complexity))
1346*f6dc9357SAndroid Build Coastguard Worker     }
1347*f6dc9357SAndroid Build Coastguard Worker     if (numVols != 1)
1348*f6dc9357SAndroid Build Coastguard Worker     {
1349*f6dc9357SAndroid Build Coastguard Worker       const UInt64 volIndex2 = volIndex;
1350*f6dc9357SAndroid Build Coastguard Worker       RINOK(openCallback->SetCompleted(numVols == 1 ? NULL : &volIndex2, &complexityStart))
1351*f6dc9357SAndroid Build Coastguard Worker     }
1352*f6dc9357SAndroid Build Coastguard Worker   }
1353*f6dc9357SAndroid Build Coastguard Worker 
1354*f6dc9357SAndroid Build Coastguard Worker   UInt64 lastSector = 0;
1355*f6dc9357SAndroid Build Coastguard Worker   UInt64 lastVirtCluster = 0;
1356*f6dc9357SAndroid Build Coastguard Worker   size_t numProcessed_Prev = 0;
1357*f6dc9357SAndroid Build Coastguard Worker 
1358*f6dc9357SAndroid Build Coastguard Worker   for (size_t i = 0; i < numGdeEntries; i++)
1359*f6dc9357SAndroid Build Coastguard Worker   {
1360*f6dc9357SAndroid Build Coastguard Worker     const size_t k_NumSectors = (size_t)1 << (k_NumMidBits - 9 + 2);
1361*f6dc9357SAndroid Build Coastguard Worker     const size_t k_NumMidItems = (size_t)1 << k_NumMidBits;
1362*f6dc9357SAndroid Build Coastguard Worker 
1363*f6dc9357SAndroid Build Coastguard Worker     CByteBuffer &buf = Tables.AddNew();
1364*f6dc9357SAndroid Build Coastguard Worker 
1365*f6dc9357SAndroid Build Coastguard Worker     {
1366*f6dc9357SAndroid Build Coastguard Worker       const UInt32 v = Get32((const Byte *)table + (size_t)i * 4);
1367*f6dc9357SAndroid Build Coastguard Worker       if (v == 0 || v == ZeroSector)
1368*f6dc9357SAndroid Build Coastguard Worker         continue;
1369*f6dc9357SAndroid Build Coastguard Worker       if (openCallback && (i - numProcessed_Prev) >= 1024)
1370*f6dc9357SAndroid Build Coastguard Worker       {
1371*f6dc9357SAndroid Build Coastguard Worker         const UInt64 comp = complexityStart + ((UInt64)i << (k_NumMidBits + 2));
1372*f6dc9357SAndroid Build Coastguard Worker         const UInt64 volIndex2 = volIndex;
1373*f6dc9357SAndroid Build Coastguard Worker         RINOK(openCallback->SetCompleted(numVols == 1 ? NULL : &volIndex2, &comp))
1374*f6dc9357SAndroid Build Coastguard Worker         numProcessed_Prev = i;
1375*f6dc9357SAndroid Build Coastguard Worker       }
1376*f6dc9357SAndroid Build Coastguard Worker 
1377*f6dc9357SAndroid Build Coastguard Worker       if (h.Is_Marker())
1378*f6dc9357SAndroid Build Coastguard Worker       {
1379*f6dc9357SAndroid Build Coastguard Worker         Byte buf2[1 << 9];
1380*f6dc9357SAndroid Build Coastguard Worker         if (ReadForHeader(stream, v - 1, buf2, 1) != S_OK)
1381*f6dc9357SAndroid Build Coastguard Worker           return S_FALSE;
1382*f6dc9357SAndroid Build Coastguard Worker         {
1383*f6dc9357SAndroid Build Coastguard Worker           CMarker m;
1384*f6dc9357SAndroid Build Coastguard Worker           m.Parse(buf2);
1385*f6dc9357SAndroid Build Coastguard Worker           if (m.Type != k_Marker_GRAIN_TABLE
1386*f6dc9357SAndroid Build Coastguard Worker             || m.NumSectors != k_NumSectors
1387*f6dc9357SAndroid Build Coastguard Worker             || m.SpecSize != 0)
1388*f6dc9357SAndroid Build Coastguard Worker             return S_FALSE;
1389*f6dc9357SAndroid Build Coastguard Worker         }
1390*f6dc9357SAndroid Build Coastguard Worker       }
1391*f6dc9357SAndroid Build Coastguard Worker 
1392*f6dc9357SAndroid Build Coastguard Worker       buf.Alloc(k_NumMidItems * 4);
1393*f6dc9357SAndroid Build Coastguard Worker       RINOK(ReadForHeader(stream, v, buf, k_NumSectors))
1394*f6dc9357SAndroid Build Coastguard Worker     }
1395*f6dc9357SAndroid Build Coastguard Worker 
1396*f6dc9357SAndroid Build Coastguard Worker     for (size_t k = 0; k < k_NumMidItems; k++)
1397*f6dc9357SAndroid Build Coastguard Worker     {
1398*f6dc9357SAndroid Build Coastguard Worker       const UInt32 v = Get32((const Byte *)buf + (size_t)k * 4);
1399*f6dc9357SAndroid Build Coastguard Worker       if (v == 0 || v == ZeroSector)
1400*f6dc9357SAndroid Build Coastguard Worker         continue;
1401*f6dc9357SAndroid Build Coastguard Worker       if (v < h.overHead)
1402*f6dc9357SAndroid Build Coastguard Worker         return S_FALSE;
1403*f6dc9357SAndroid Build Coastguard Worker       if (lastSector < v)
1404*f6dc9357SAndroid Build Coastguard Worker       {
1405*f6dc9357SAndroid Build Coastguard Worker         lastSector = v;
1406*f6dc9357SAndroid Build Coastguard Worker         if (NeedDeflate)
1407*f6dc9357SAndroid Build Coastguard Worker           lastVirtCluster = ((UInt64)i << k_NumMidBits) + k;
1408*f6dc9357SAndroid Build Coastguard Worker       }
1409*f6dc9357SAndroid Build Coastguard Worker     }
1410*f6dc9357SAndroid Build Coastguard Worker   }
1411*f6dc9357SAndroid Build Coastguard Worker 
1412*f6dc9357SAndroid Build Coastguard Worker   if (!NeedDeflate)
1413*f6dc9357SAndroid Build Coastguard Worker   {
1414*f6dc9357SAndroid Build Coastguard Worker     UInt64 end = ((UInt64)lastSector << 9) + clusterSize;
1415*f6dc9357SAndroid Build Coastguard Worker     if (PhySize < end)
1416*f6dc9357SAndroid Build Coastguard Worker       PhySize = end;
1417*f6dc9357SAndroid Build Coastguard Worker   }
1418*f6dc9357SAndroid Build Coastguard Worker   else if (lastSector != 0)
1419*f6dc9357SAndroid Build Coastguard Worker   {
1420*f6dc9357SAndroid Build Coastguard Worker     Byte buf[1 << 9];
1421*f6dc9357SAndroid Build Coastguard Worker     if (ReadForHeader(stream, lastSector, buf, 1) == S_OK)
1422*f6dc9357SAndroid Build Coastguard Worker     {
1423*f6dc9357SAndroid Build Coastguard Worker       UInt64 lba = Get64(buf);
1424*f6dc9357SAndroid Build Coastguard Worker       if (lba == (lastVirtCluster << (ClusterBits - 9)))
1425*f6dc9357SAndroid Build Coastguard Worker       {
1426*f6dc9357SAndroid Build Coastguard Worker         UInt32 dataSize = Get32(buf + 8);
1427*f6dc9357SAndroid Build Coastguard Worker         size_t dataSize2 = (size_t)dataSize + 12;
1428*f6dc9357SAndroid Build Coastguard Worker         dataSize2 = (dataSize2 + 511) & ~(size_t)511;
1429*f6dc9357SAndroid Build Coastguard Worker         UInt64 end = ((UInt64)lastSector << 9) + dataSize2;
1430*f6dc9357SAndroid Build Coastguard Worker         if (PhySize < end)
1431*f6dc9357SAndroid Build Coastguard Worker           PhySize = end;
1432*f6dc9357SAndroid Build Coastguard Worker       }
1433*f6dc9357SAndroid Build Coastguard Worker     }
1434*f6dc9357SAndroid Build Coastguard Worker   }
1435*f6dc9357SAndroid Build Coastguard Worker 
1436*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
1437*f6dc9357SAndroid Build Coastguard Worker }
1438*f6dc9357SAndroid Build Coastguard Worker 
1439*f6dc9357SAndroid Build Coastguard Worker 
1440*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Close())
1441*f6dc9357SAndroid Build Coastguard Worker {
1442*f6dc9357SAndroid Build Coastguard Worker   _phySize = 0;
1443*f6dc9357SAndroid Build Coastguard Worker 
1444*f6dc9357SAndroid Build Coastguard Worker   _cacheCluster = (UInt64)(Int64)-1;
1445*f6dc9357SAndroid Build Coastguard Worker   _cacheExtent = (unsigned)(int)-1;
1446*f6dc9357SAndroid Build Coastguard Worker 
1447*f6dc9357SAndroid Build Coastguard Worker   _clusterBitsMax = 0;
1448*f6dc9357SAndroid Build Coastguard Worker 
1449*f6dc9357SAndroid Build Coastguard Worker   _isArc = false;
1450*f6dc9357SAndroid Build Coastguard Worker   _unsupported = false;
1451*f6dc9357SAndroid Build Coastguard Worker   _unsupportedSome = false;
1452*f6dc9357SAndroid Build Coastguard Worker   _headerError = false;
1453*f6dc9357SAndroid Build Coastguard Worker   _missingVol = false;
1454*f6dc9357SAndroid Build Coastguard Worker   _isMultiVol = false;
1455*f6dc9357SAndroid Build Coastguard Worker   _needDeflate = false;
1456*f6dc9357SAndroid Build Coastguard Worker 
1457*f6dc9357SAndroid Build Coastguard Worker   _missingVolName.Empty();
1458*f6dc9357SAndroid Build Coastguard Worker 
1459*f6dc9357SAndroid Build Coastguard Worker   _descriptorBuf.Free();
1460*f6dc9357SAndroid Build Coastguard Worker   _descriptor.Clear();
1461*f6dc9357SAndroid Build Coastguard Worker 
1462*f6dc9357SAndroid Build Coastguard Worker   // CHandlerImg:
1463*f6dc9357SAndroid Build Coastguard Worker   Clear_HandlerImg_Vars();
1464*f6dc9357SAndroid Build Coastguard Worker   Stream.Release();
1465*f6dc9357SAndroid Build Coastguard Worker 
1466*f6dc9357SAndroid Build Coastguard Worker   _extents.Clear();
1467*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
1468*f6dc9357SAndroid Build Coastguard Worker }
1469*f6dc9357SAndroid Build Coastguard Worker 
1470*f6dc9357SAndroid Build Coastguard Worker 
1471*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetStream(UInt32 /* index */, ISequentialInStream **stream))
1472*f6dc9357SAndroid Build Coastguard Worker {
1473*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_BEGIN
1474*f6dc9357SAndroid Build Coastguard Worker   *stream = NULL;
1475*f6dc9357SAndroid Build Coastguard Worker 
1476*f6dc9357SAndroid Build Coastguard Worker   if (_unsupported)
1477*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
1478*f6dc9357SAndroid Build Coastguard Worker 
1479*f6dc9357SAndroid Build Coastguard Worker   ClearStreamVars();
1480*f6dc9357SAndroid Build Coastguard Worker   // _stream_UsePackSize = true;
1481*f6dc9357SAndroid Build Coastguard Worker 
1482*f6dc9357SAndroid Build Coastguard Worker   if (_needDeflate)
1483*f6dc9357SAndroid Build Coastguard Worker   {
1484*f6dc9357SAndroid Build Coastguard Worker     if (!_bufInStream)
1485*f6dc9357SAndroid Build Coastguard Worker     {
1486*f6dc9357SAndroid Build Coastguard Worker       _bufInStreamSpec = new CBufInStream;
1487*f6dc9357SAndroid Build Coastguard Worker       _bufInStream = _bufInStreamSpec;
1488*f6dc9357SAndroid Build Coastguard Worker     }
1489*f6dc9357SAndroid Build Coastguard Worker 
1490*f6dc9357SAndroid Build Coastguard Worker     if (!_bufOutStream)
1491*f6dc9357SAndroid Build Coastguard Worker     {
1492*f6dc9357SAndroid Build Coastguard Worker       _bufOutStreamSpec = new CBufPtrSeqOutStream();
1493*f6dc9357SAndroid Build Coastguard Worker       _bufOutStream = _bufOutStreamSpec;
1494*f6dc9357SAndroid Build Coastguard Worker     }
1495*f6dc9357SAndroid Build Coastguard Worker 
1496*f6dc9357SAndroid Build Coastguard Worker     if (!_zlibDecoder)
1497*f6dc9357SAndroid Build Coastguard Worker     {
1498*f6dc9357SAndroid Build Coastguard Worker       _zlibDecoderSpec = new NCompress::NZlib::CDecoder;
1499*f6dc9357SAndroid Build Coastguard Worker       _zlibDecoder = _zlibDecoderSpec;
1500*f6dc9357SAndroid Build Coastguard Worker     }
1501*f6dc9357SAndroid Build Coastguard Worker 
1502*f6dc9357SAndroid Build Coastguard Worker     const size_t clusterSize = (size_t)1 << _clusterBitsMax;
1503*f6dc9357SAndroid Build Coastguard Worker     _cache.AllocAtLeast(clusterSize);
1504*f6dc9357SAndroid Build Coastguard Worker     _cacheCompressed.AllocAtLeast(clusterSize * 2);
1505*f6dc9357SAndroid Build Coastguard Worker   }
1506*f6dc9357SAndroid Build Coastguard Worker 
1507*f6dc9357SAndroid Build Coastguard Worker   FOR_VECTOR (i, _extents)
1508*f6dc9357SAndroid Build Coastguard Worker   {
1509*f6dc9357SAndroid Build Coastguard Worker     RINOK(_extents[i].InitAndSeek())
1510*f6dc9357SAndroid Build Coastguard Worker   }
1511*f6dc9357SAndroid Build Coastguard Worker 
1512*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<ISequentialInStream> streamTemp = this;
1513*f6dc9357SAndroid Build Coastguard Worker   InitAndSeekMain();
1514*f6dc9357SAndroid Build Coastguard Worker   *stream = streamTemp.Detach();
1515*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
1516*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_END
1517*f6dc9357SAndroid Build Coastguard Worker }
1518*f6dc9357SAndroid Build Coastguard Worker 
1519*f6dc9357SAndroid Build Coastguard Worker 
1520*f6dc9357SAndroid Build Coastguard Worker REGISTER_ARC_I(
1521*f6dc9357SAndroid Build Coastguard Worker   "VMDK", "vmdk", NULL, 0xC8,
1522*f6dc9357SAndroid Build Coastguard Worker   k_Signature,
1523*f6dc9357SAndroid Build Coastguard Worker   0,
1524*f6dc9357SAndroid Build Coastguard Worker   0,
1525*f6dc9357SAndroid Build Coastguard Worker   NULL)
1526*f6dc9357SAndroid Build Coastguard Worker 
1527*f6dc9357SAndroid Build Coastguard Worker }}
1528