xref: /aosp_15_r20/external/lzma/CPP/7zip/Archive/VdiHandler.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker // VdiHandler.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/MyBuffer.h"
12*f6dc9357SAndroid Build Coastguard Worker 
13*f6dc9357SAndroid Build Coastguard Worker #include "../../Windows/PropVariant.h"
14*f6dc9357SAndroid Build Coastguard Worker #include "../../Windows/PropVariantUtils.h"
15*f6dc9357SAndroid Build Coastguard Worker 
16*f6dc9357SAndroid Build Coastguard Worker #include "../Common/RegisterArc.h"
17*f6dc9357SAndroid Build Coastguard Worker #include "../Common/StreamUtils.h"
18*f6dc9357SAndroid Build Coastguard Worker 
19*f6dc9357SAndroid Build Coastguard Worker #include "HandlerCont.h"
20*f6dc9357SAndroid Build Coastguard Worker 
21*f6dc9357SAndroid Build Coastguard Worker #define Get32(p) GetUi32(p)
22*f6dc9357SAndroid Build Coastguard Worker #define Get64(p) GetUi64(p)
23*f6dc9357SAndroid Build Coastguard Worker 
24*f6dc9357SAndroid Build Coastguard Worker using namespace NWindows;
25*f6dc9357SAndroid Build Coastguard Worker 
26*f6dc9357SAndroid Build Coastguard Worker namespace NArchive {
27*f6dc9357SAndroid Build Coastguard Worker namespace NVdi {
28*f6dc9357SAndroid Build Coastguard Worker 
29*f6dc9357SAndroid Build Coastguard Worker static const Byte k_Signature[] = { 0x7F, 0x10, 0xDA, 0xBE };
30*f6dc9357SAndroid Build Coastguard Worker 
31*f6dc9357SAndroid Build Coastguard Worker static const unsigned k_ClusterBits = 20;
32*f6dc9357SAndroid Build Coastguard Worker static const UInt32 k_ClusterSize = (UInt32)1 << k_ClusterBits;
33*f6dc9357SAndroid Build Coastguard Worker 
34*f6dc9357SAndroid Build Coastguard Worker 
35*f6dc9357SAndroid Build Coastguard Worker /*
36*f6dc9357SAndroid Build Coastguard Worker VDI_IMAGE_BLOCK_FREE = (~0) // returns any random data
37*f6dc9357SAndroid Build Coastguard Worker VDI_IMAGE_BLOCK_ZERO = (~1) // returns zeros
38*f6dc9357SAndroid Build Coastguard Worker */
39*f6dc9357SAndroid Build Coastguard Worker 
40*f6dc9357SAndroid Build Coastguard Worker // static const UInt32 k_ClusterType_Free  = 0xffffffff;
41*f6dc9357SAndroid Build Coastguard Worker static const UInt32 k_ClusterType_Zero  = 0xfffffffe;
42*f6dc9357SAndroid Build Coastguard Worker 
43*f6dc9357SAndroid Build Coastguard Worker #define IS_CLUSTER_ALLOCATED(v) ((UInt32)(v) < k_ClusterType_Zero)
44*f6dc9357SAndroid Build Coastguard Worker 
45*f6dc9357SAndroid Build Coastguard Worker 
46*f6dc9357SAndroid Build Coastguard Worker // static const UInt32 kDiskType_Dynamic = 1;
47*f6dc9357SAndroid Build Coastguard Worker // static const UInt32 kDiskType_Static = 2;
48*f6dc9357SAndroid Build Coastguard Worker 
49*f6dc9357SAndroid Build Coastguard Worker static const char * const kDiskTypes[] =
50*f6dc9357SAndroid Build Coastguard Worker {
51*f6dc9357SAndroid Build Coastguard Worker     "0"
52*f6dc9357SAndroid Build Coastguard Worker   , "Dynamic"
53*f6dc9357SAndroid Build Coastguard Worker   , "Static"
54*f6dc9357SAndroid Build Coastguard Worker   , "Undo"
55*f6dc9357SAndroid Build Coastguard Worker   , "Diff"
56*f6dc9357SAndroid Build Coastguard Worker };
57*f6dc9357SAndroid Build Coastguard Worker 
58*f6dc9357SAndroid Build Coastguard Worker 
59*f6dc9357SAndroid Build Coastguard Worker enum EGuidType
60*f6dc9357SAndroid Build Coastguard Worker {
61*f6dc9357SAndroid Build Coastguard Worker   k_GuidType_Creat,
62*f6dc9357SAndroid Build Coastguard Worker   k_GuidType_Modif,
63*f6dc9357SAndroid Build Coastguard Worker   k_GuidType_Link,
64*f6dc9357SAndroid Build Coastguard Worker   k_GuidType_PModif
65*f6dc9357SAndroid Build Coastguard Worker };
66*f6dc9357SAndroid Build Coastguard Worker 
67*f6dc9357SAndroid Build Coastguard Worker static const unsigned kNumGuids = 4;
68*f6dc9357SAndroid Build Coastguard Worker static const char * const kGuidNames[kNumGuids] =
69*f6dc9357SAndroid Build Coastguard Worker {
70*f6dc9357SAndroid Build Coastguard Worker     "Creat "
71*f6dc9357SAndroid Build Coastguard Worker   , "Modif "
72*f6dc9357SAndroid Build Coastguard Worker   , "Link  "
73*f6dc9357SAndroid Build Coastguard Worker   , "PModif"
74*f6dc9357SAndroid Build Coastguard Worker };
75*f6dc9357SAndroid Build Coastguard Worker 
IsEmptyGuid(const Byte * data)76*f6dc9357SAndroid Build Coastguard Worker static bool IsEmptyGuid(const Byte *data)
77*f6dc9357SAndroid Build Coastguard Worker {
78*f6dc9357SAndroid Build Coastguard Worker   for (unsigned i = 0; i < 16; i++)
79*f6dc9357SAndroid Build Coastguard Worker     if (data[i] != 0)
80*f6dc9357SAndroid Build Coastguard Worker       return false;
81*f6dc9357SAndroid Build Coastguard Worker   return true;
82*f6dc9357SAndroid Build Coastguard Worker }
83*f6dc9357SAndroid Build Coastguard Worker 
84*f6dc9357SAndroid Build Coastguard Worker 
85*f6dc9357SAndroid Build Coastguard Worker 
86*f6dc9357SAndroid Build Coastguard Worker Z7_class_CHandler_final: public CHandlerImg
87*f6dc9357SAndroid Build Coastguard Worker {
88*f6dc9357SAndroid Build Coastguard Worker   UInt32 _dataOffset;
89*f6dc9357SAndroid Build Coastguard Worker   CByteBuffer _table;
90*f6dc9357SAndroid Build Coastguard Worker   UInt64 _phySize;
91*f6dc9357SAndroid Build Coastguard Worker   UInt32 _imageType;
92*f6dc9357SAndroid Build Coastguard Worker   bool _isArc;
93*f6dc9357SAndroid Build Coastguard Worker   bool _unsupported;
94*f6dc9357SAndroid Build Coastguard Worker 
95*f6dc9357SAndroid Build Coastguard Worker   Byte Guids[kNumGuids][16];
96*f6dc9357SAndroid Build Coastguard Worker 
97*f6dc9357SAndroid Build Coastguard Worker   HRESULT Seek2(UInt64 offset)
98*f6dc9357SAndroid Build Coastguard Worker   {
99*f6dc9357SAndroid Build Coastguard Worker     _posInArc = offset;
100*f6dc9357SAndroid Build Coastguard Worker     return InStream_SeekSet(Stream, offset);
101*f6dc9357SAndroid Build Coastguard Worker   }
102*f6dc9357SAndroid Build Coastguard Worker 
103*f6dc9357SAndroid Build Coastguard Worker   HRESULT InitAndSeek()
104*f6dc9357SAndroid Build Coastguard Worker   {
105*f6dc9357SAndroid Build Coastguard Worker     _virtPos = 0;
106*f6dc9357SAndroid Build Coastguard Worker     return Seek2(0);
107*f6dc9357SAndroid Build Coastguard Worker   }
108*f6dc9357SAndroid Build Coastguard Worker 
109*f6dc9357SAndroid Build Coastguard Worker   HRESULT Open2(IInStream *stream, IArchiveOpenCallback *openCallback) Z7_override;
110*f6dc9357SAndroid Build Coastguard Worker 
111*f6dc9357SAndroid Build Coastguard Worker public:
112*f6dc9357SAndroid Build Coastguard Worker   Z7_IFACE_COM7_IMP(IInArchive_Img)
113*f6dc9357SAndroid Build Coastguard Worker 
114*f6dc9357SAndroid Build Coastguard Worker   Z7_IFACE_COM7_IMP(IInArchiveGetStream)
115*f6dc9357SAndroid Build Coastguard Worker   Z7_IFACE_COM7_IMP(ISequentialInStream)
116*f6dc9357SAndroid Build Coastguard Worker };
117*f6dc9357SAndroid Build Coastguard Worker 
118*f6dc9357SAndroid Build Coastguard Worker 
119*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Read(void *data, UInt32 size, UInt32 *processedSize))
120*f6dc9357SAndroid Build Coastguard Worker {
121*f6dc9357SAndroid Build Coastguard Worker   if (processedSize)
122*f6dc9357SAndroid Build Coastguard Worker     *processedSize = 0;
123*f6dc9357SAndroid Build Coastguard Worker   if (_virtPos >= _size)
124*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
125*f6dc9357SAndroid Build Coastguard Worker   {
126*f6dc9357SAndroid Build Coastguard Worker     UInt64 rem = _size - _virtPos;
127*f6dc9357SAndroid Build Coastguard Worker     if (size > rem)
128*f6dc9357SAndroid Build Coastguard Worker       size = (UInt32)rem;
129*f6dc9357SAndroid Build Coastguard Worker     if (size == 0)
130*f6dc9357SAndroid Build Coastguard Worker       return S_OK;
131*f6dc9357SAndroid Build Coastguard Worker   }
132*f6dc9357SAndroid Build Coastguard Worker 
133*f6dc9357SAndroid Build Coastguard Worker   {
134*f6dc9357SAndroid Build Coastguard Worker     UInt64 cluster = _virtPos >> k_ClusterBits;
135*f6dc9357SAndroid Build Coastguard Worker     UInt32 lowBits = (UInt32)_virtPos & (k_ClusterSize - 1);
136*f6dc9357SAndroid Build Coastguard Worker     {
137*f6dc9357SAndroid Build Coastguard Worker       UInt32 rem = k_ClusterSize - lowBits;
138*f6dc9357SAndroid Build Coastguard Worker       if (size > rem)
139*f6dc9357SAndroid Build Coastguard Worker         size = rem;
140*f6dc9357SAndroid Build Coastguard Worker     }
141*f6dc9357SAndroid Build Coastguard Worker 
142*f6dc9357SAndroid Build Coastguard Worker     cluster <<= 2;
143*f6dc9357SAndroid Build Coastguard Worker     if (cluster < _table.Size())
144*f6dc9357SAndroid Build Coastguard Worker     {
145*f6dc9357SAndroid Build Coastguard Worker       const Byte *p = (const Byte *)_table + (size_t)cluster;
146*f6dc9357SAndroid Build Coastguard Worker       const UInt32 v = Get32(p);
147*f6dc9357SAndroid Build Coastguard Worker       if (IS_CLUSTER_ALLOCATED(v))
148*f6dc9357SAndroid Build Coastguard Worker       {
149*f6dc9357SAndroid Build Coastguard Worker         UInt64 offset = _dataOffset + ((UInt64)v << k_ClusterBits);
150*f6dc9357SAndroid Build Coastguard Worker         offset += lowBits;
151*f6dc9357SAndroid Build Coastguard Worker         if (offset != _posInArc)
152*f6dc9357SAndroid Build Coastguard Worker         {
153*f6dc9357SAndroid Build Coastguard Worker           RINOK(Seek2(offset))
154*f6dc9357SAndroid Build Coastguard Worker         }
155*f6dc9357SAndroid Build Coastguard Worker         HRESULT res = Stream->Read(data, size, &size);
156*f6dc9357SAndroid Build Coastguard Worker         _posInArc += size;
157*f6dc9357SAndroid Build Coastguard Worker         _virtPos += size;
158*f6dc9357SAndroid Build Coastguard Worker         if (processedSize)
159*f6dc9357SAndroid Build Coastguard Worker           *processedSize = size;
160*f6dc9357SAndroid Build Coastguard Worker         return res;
161*f6dc9357SAndroid Build Coastguard Worker       }
162*f6dc9357SAndroid Build Coastguard Worker     }
163*f6dc9357SAndroid Build Coastguard Worker 
164*f6dc9357SAndroid Build Coastguard Worker     memset(data, 0, size);
165*f6dc9357SAndroid Build Coastguard Worker     _virtPos += size;
166*f6dc9357SAndroid Build Coastguard Worker     if (processedSize)
167*f6dc9357SAndroid Build Coastguard Worker       *processedSize = size;
168*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
169*f6dc9357SAndroid Build Coastguard Worker   }
170*f6dc9357SAndroid Build Coastguard Worker }
171*f6dc9357SAndroid Build Coastguard Worker 
172*f6dc9357SAndroid Build Coastguard Worker 
173*f6dc9357SAndroid Build Coastguard Worker static const Byte kProps[] =
174*f6dc9357SAndroid Build Coastguard Worker {
175*f6dc9357SAndroid Build Coastguard Worker   kpidSize,
176*f6dc9357SAndroid Build Coastguard Worker   kpidPackSize
177*f6dc9357SAndroid Build Coastguard Worker };
178*f6dc9357SAndroid Build Coastguard Worker 
179*f6dc9357SAndroid Build Coastguard Worker static const Byte kArcProps[] =
180*f6dc9357SAndroid Build Coastguard Worker {
181*f6dc9357SAndroid Build Coastguard Worker   kpidHeadersSize,
182*f6dc9357SAndroid Build Coastguard Worker   kpidMethod,
183*f6dc9357SAndroid Build Coastguard Worker   kpidComment,
184*f6dc9357SAndroid Build Coastguard Worker   kpidName
185*f6dc9357SAndroid Build Coastguard Worker };
186*f6dc9357SAndroid Build Coastguard Worker 
187*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_Props
188*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_ArcProps
189*f6dc9357SAndroid Build Coastguard Worker 
190*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
191*f6dc9357SAndroid Build Coastguard Worker {
192*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_BEGIN
193*f6dc9357SAndroid Build Coastguard Worker   NCOM::CPropVariant prop;
194*f6dc9357SAndroid Build Coastguard Worker 
195*f6dc9357SAndroid Build Coastguard Worker   switch (propID)
196*f6dc9357SAndroid Build Coastguard Worker   {
197*f6dc9357SAndroid Build Coastguard Worker     case kpidMainSubfile: prop = (UInt32)0; break;
198*f6dc9357SAndroid Build Coastguard Worker     case kpidPhySize: if (_phySize != 0) prop = _phySize; break;
199*f6dc9357SAndroid Build Coastguard Worker     case kpidHeadersSize: prop = _dataOffset; break;
200*f6dc9357SAndroid Build Coastguard Worker 
201*f6dc9357SAndroid Build Coastguard Worker     case kpidMethod:
202*f6dc9357SAndroid Build Coastguard Worker     {
203*f6dc9357SAndroid Build Coastguard Worker       TYPE_TO_PROP(kDiskTypes, _imageType, prop);
204*f6dc9357SAndroid Build Coastguard Worker       break;
205*f6dc9357SAndroid Build Coastguard Worker     }
206*f6dc9357SAndroid Build Coastguard Worker 
207*f6dc9357SAndroid Build Coastguard Worker     case kpidErrorFlags:
208*f6dc9357SAndroid Build Coastguard Worker     {
209*f6dc9357SAndroid Build Coastguard Worker       UInt32 v = 0;
210*f6dc9357SAndroid Build Coastguard Worker       if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;
211*f6dc9357SAndroid Build Coastguard Worker       if (_unsupported) v |= kpv_ErrorFlags_UnsupportedMethod;
212*f6dc9357SAndroid Build Coastguard Worker       // if (_headerError) v |= kpv_ErrorFlags_HeadersError;
213*f6dc9357SAndroid Build Coastguard Worker       if (!Stream && v == 0 && _isArc)
214*f6dc9357SAndroid Build Coastguard Worker         v = kpv_ErrorFlags_HeadersError;
215*f6dc9357SAndroid Build Coastguard Worker       if (v != 0)
216*f6dc9357SAndroid Build Coastguard Worker         prop = v;
217*f6dc9357SAndroid Build Coastguard Worker       break;
218*f6dc9357SAndroid Build Coastguard Worker     }
219*f6dc9357SAndroid Build Coastguard Worker 
220*f6dc9357SAndroid Build Coastguard Worker     case kpidComment:
221*f6dc9357SAndroid Build Coastguard Worker     {
222*f6dc9357SAndroid Build Coastguard Worker       AString s;
223*f6dc9357SAndroid Build Coastguard Worker       for (unsigned i = 0; i < kNumGuids; i++)
224*f6dc9357SAndroid Build Coastguard Worker       {
225*f6dc9357SAndroid Build Coastguard Worker         const Byte *guid = Guids[i];
226*f6dc9357SAndroid Build Coastguard Worker         if (!IsEmptyGuid(guid))
227*f6dc9357SAndroid Build Coastguard Worker         {
228*f6dc9357SAndroid Build Coastguard Worker           s.Add_LF();
229*f6dc9357SAndroid Build Coastguard Worker           s += kGuidNames[i];
230*f6dc9357SAndroid Build Coastguard Worker           s += " : ";
231*f6dc9357SAndroid Build Coastguard Worker           char temp[64];
232*f6dc9357SAndroid Build Coastguard Worker           RawLeGuidToString_Braced(guid, temp);
233*f6dc9357SAndroid Build Coastguard Worker           MyStringLower_Ascii(temp);
234*f6dc9357SAndroid Build Coastguard Worker           s += temp;
235*f6dc9357SAndroid Build Coastguard Worker         }
236*f6dc9357SAndroid Build Coastguard Worker       }
237*f6dc9357SAndroid Build Coastguard Worker       if (!s.IsEmpty())
238*f6dc9357SAndroid Build Coastguard Worker         prop = s;
239*f6dc9357SAndroid Build Coastguard Worker       break;
240*f6dc9357SAndroid Build Coastguard Worker     }
241*f6dc9357SAndroid Build Coastguard Worker 
242*f6dc9357SAndroid Build Coastguard Worker     case kpidName:
243*f6dc9357SAndroid Build Coastguard Worker     {
244*f6dc9357SAndroid Build Coastguard Worker       const Byte *guid = Guids[k_GuidType_Creat];
245*f6dc9357SAndroid Build Coastguard Worker       if (!IsEmptyGuid(guid))
246*f6dc9357SAndroid Build Coastguard Worker       {
247*f6dc9357SAndroid Build Coastguard Worker         char temp[64];
248*f6dc9357SAndroid Build Coastguard Worker         RawLeGuidToString_Braced(guid, temp);
249*f6dc9357SAndroid Build Coastguard Worker         MyStringLower_Ascii(temp);
250*f6dc9357SAndroid Build Coastguard Worker         MyStringCat(temp, ".vdi");
251*f6dc9357SAndroid Build Coastguard Worker         prop = temp;
252*f6dc9357SAndroid Build Coastguard Worker       }
253*f6dc9357SAndroid Build Coastguard Worker       break;
254*f6dc9357SAndroid Build Coastguard Worker     }
255*f6dc9357SAndroid Build Coastguard Worker   }
256*f6dc9357SAndroid Build Coastguard Worker 
257*f6dc9357SAndroid Build Coastguard Worker   prop.Detach(value);
258*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
259*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_END
260*f6dc9357SAndroid Build Coastguard Worker }
261*f6dc9357SAndroid Build Coastguard Worker 
262*f6dc9357SAndroid Build Coastguard Worker 
263*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value))
264*f6dc9357SAndroid Build Coastguard Worker {
265*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_BEGIN
266*f6dc9357SAndroid Build Coastguard Worker   NCOM::CPropVariant prop;
267*f6dc9357SAndroid Build Coastguard Worker 
268*f6dc9357SAndroid Build Coastguard Worker   switch (propID)
269*f6dc9357SAndroid Build Coastguard Worker   {
270*f6dc9357SAndroid Build Coastguard Worker     case kpidSize: prop = _size; break;
271*f6dc9357SAndroid Build Coastguard Worker     case kpidPackSize: prop = _phySize - _dataOffset; break;
272*f6dc9357SAndroid Build Coastguard Worker     case kpidExtension: prop = (_imgExt ? _imgExt : "img"); break;
273*f6dc9357SAndroid Build Coastguard Worker   }
274*f6dc9357SAndroid Build Coastguard Worker 
275*f6dc9357SAndroid Build Coastguard Worker   prop.Detach(value);
276*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
277*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_END
278*f6dc9357SAndroid Build Coastguard Worker }
279*f6dc9357SAndroid Build Coastguard Worker 
280*f6dc9357SAndroid Build Coastguard Worker 
281*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback * /* openCallback */)
282*f6dc9357SAndroid Build Coastguard Worker {
283*f6dc9357SAndroid Build Coastguard Worker   const unsigned kHeaderSize = 512;
284*f6dc9357SAndroid Build Coastguard Worker   Byte buf[kHeaderSize];
285*f6dc9357SAndroid Build Coastguard Worker   RINOK(ReadStream_FALSE(stream, buf, kHeaderSize))
286*f6dc9357SAndroid Build Coastguard Worker 
287*f6dc9357SAndroid Build Coastguard Worker   if (memcmp(buf + 0x40, k_Signature, sizeof(k_Signature)) != 0)
288*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
289*f6dc9357SAndroid Build Coastguard Worker 
290*f6dc9357SAndroid Build Coastguard Worker   const UInt32 version = Get32(buf + 0x44);
291*f6dc9357SAndroid Build Coastguard Worker   if (version >= 0x20000)
292*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
293*f6dc9357SAndroid Build Coastguard Worker   if (version < 0x10000)
294*f6dc9357SAndroid Build Coastguard Worker   {
295*f6dc9357SAndroid Build Coastguard Worker     _unsupported = true;
296*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
297*f6dc9357SAndroid Build Coastguard Worker   }
298*f6dc9357SAndroid Build Coastguard Worker 
299*f6dc9357SAndroid Build Coastguard Worker   const unsigned kHeaderOffset = 0x48;
300*f6dc9357SAndroid Build Coastguard Worker   const unsigned kGuidsOffsets = 0x188;
301*f6dc9357SAndroid Build Coastguard Worker   const UInt32 headerSize = Get32(buf + kHeaderOffset);
302*f6dc9357SAndroid Build Coastguard Worker   if (headerSize < kGuidsOffsets - kHeaderOffset || headerSize > 0x200 - kHeaderOffset)
303*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
304*f6dc9357SAndroid Build Coastguard Worker 
305*f6dc9357SAndroid Build Coastguard Worker   _imageType = Get32(buf + 0x4C);
306*f6dc9357SAndroid Build Coastguard Worker   // Int32 flags = Get32(buf + 0x50);
307*f6dc9357SAndroid Build Coastguard Worker   // Byte Comment[0x100]
308*f6dc9357SAndroid Build Coastguard Worker 
309*f6dc9357SAndroid Build Coastguard Worker   const UInt32 tableOffset = Get32(buf + 0x154);
310*f6dc9357SAndroid Build Coastguard Worker   if (tableOffset < 0x200)
311*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
312*f6dc9357SAndroid Build Coastguard Worker 
313*f6dc9357SAndroid Build Coastguard Worker   _dataOffset = Get32(buf + 0x158);
314*f6dc9357SAndroid Build Coastguard Worker 
315*f6dc9357SAndroid Build Coastguard Worker   // UInt32 geometry[3];
316*f6dc9357SAndroid Build Coastguard Worker 
317*f6dc9357SAndroid Build Coastguard Worker   const UInt32 sectorSize = Get32(buf + 0x168);
318*f6dc9357SAndroid Build Coastguard Worker   if (sectorSize != 0x200)
319*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
320*f6dc9357SAndroid Build Coastguard Worker 
321*f6dc9357SAndroid Build Coastguard Worker   _size = Get64(buf + 0x170);
322*f6dc9357SAndroid Build Coastguard Worker   const UInt32 blockSize = Get32(buf + 0x178);
323*f6dc9357SAndroid Build Coastguard Worker   const UInt32 totalBlocks = Get32(buf + 0x180);
324*f6dc9357SAndroid Build Coastguard Worker   const UInt32 numAllocatedBlocks = Get32(buf + 0x184);
325*f6dc9357SAndroid Build Coastguard Worker 
326*f6dc9357SAndroid Build Coastguard Worker   _isArc = true;
327*f6dc9357SAndroid Build Coastguard Worker 
328*f6dc9357SAndroid Build Coastguard Worker   if (_dataOffset < tableOffset)
329*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
330*f6dc9357SAndroid Build Coastguard Worker 
331*f6dc9357SAndroid Build Coastguard Worker   if (_imageType > 4)
332*f6dc9357SAndroid Build Coastguard Worker     _unsupported = true;
333*f6dc9357SAndroid Build Coastguard Worker 
334*f6dc9357SAndroid Build Coastguard Worker   if (blockSize != k_ClusterSize)
335*f6dc9357SAndroid Build Coastguard Worker   {
336*f6dc9357SAndroid Build Coastguard Worker     _unsupported = true;
337*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
338*f6dc9357SAndroid Build Coastguard Worker   }
339*f6dc9357SAndroid Build Coastguard Worker 
340*f6dc9357SAndroid Build Coastguard Worker   if (headerSize >= kGuidsOffsets + kNumGuids * 16 - kHeaderOffset)
341*f6dc9357SAndroid Build Coastguard Worker   {
342*f6dc9357SAndroid Build Coastguard Worker     for (unsigned i = 0; i < kNumGuids; i++)
343*f6dc9357SAndroid Build Coastguard Worker       memcpy(Guids[i], buf + kGuidsOffsets + 16 * i, 16);
344*f6dc9357SAndroid Build Coastguard Worker 
345*f6dc9357SAndroid Build Coastguard Worker     if (!IsEmptyGuid(Guids[k_GuidType_Link]) ||
346*f6dc9357SAndroid Build Coastguard Worker         !IsEmptyGuid(Guids[k_GuidType_PModif]))
347*f6dc9357SAndroid Build Coastguard Worker       _unsupported = true;
348*f6dc9357SAndroid Build Coastguard Worker   }
349*f6dc9357SAndroid Build Coastguard Worker 
350*f6dc9357SAndroid Build Coastguard Worker   {
351*f6dc9357SAndroid Build Coastguard Worker     UInt64 size2 = (UInt64)totalBlocks << k_ClusterBits;
352*f6dc9357SAndroid Build Coastguard Worker     if (size2 < _size)
353*f6dc9357SAndroid Build Coastguard Worker     {
354*f6dc9357SAndroid Build Coastguard Worker       _unsupported = true;
355*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
356*f6dc9357SAndroid Build Coastguard Worker     }
357*f6dc9357SAndroid Build Coastguard Worker     /*
358*f6dc9357SAndroid Build Coastguard Worker     if (size2 > _size)
359*f6dc9357SAndroid Build Coastguard Worker       _size = size2;
360*f6dc9357SAndroid Build Coastguard Worker     */
361*f6dc9357SAndroid Build Coastguard Worker   }
362*f6dc9357SAndroid Build Coastguard Worker 
363*f6dc9357SAndroid Build Coastguard Worker   {
364*f6dc9357SAndroid Build Coastguard Worker     UInt32 tableReserved = _dataOffset - tableOffset;
365*f6dc9357SAndroid Build Coastguard Worker     if ((tableReserved >> 2) < totalBlocks)
366*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
367*f6dc9357SAndroid Build Coastguard Worker   }
368*f6dc9357SAndroid Build Coastguard Worker 
369*f6dc9357SAndroid Build Coastguard Worker   _phySize = _dataOffset + ((UInt64)numAllocatedBlocks << k_ClusterBits);
370*f6dc9357SAndroid Build Coastguard Worker 
371*f6dc9357SAndroid Build Coastguard Worker   const size_t numBytes = (size_t)totalBlocks * 4;
372*f6dc9357SAndroid Build Coastguard Worker   if ((numBytes >> 2) != totalBlocks)
373*f6dc9357SAndroid Build Coastguard Worker   {
374*f6dc9357SAndroid Build Coastguard Worker     _unsupported = true;
375*f6dc9357SAndroid Build Coastguard Worker     return E_OUTOFMEMORY;
376*f6dc9357SAndroid Build Coastguard Worker   }
377*f6dc9357SAndroid Build Coastguard Worker 
378*f6dc9357SAndroid Build Coastguard Worker   _table.Alloc(numBytes);
379*f6dc9357SAndroid Build Coastguard Worker   RINOK(InStream_SeekSet(stream, tableOffset))
380*f6dc9357SAndroid Build Coastguard Worker   RINOK(ReadStream_FALSE(stream, _table, numBytes))
381*f6dc9357SAndroid Build Coastguard Worker 
382*f6dc9357SAndroid Build Coastguard Worker   const Byte *data = _table;
383*f6dc9357SAndroid Build Coastguard Worker   for (UInt32 i = 0; i < totalBlocks; i++)
384*f6dc9357SAndroid Build Coastguard Worker   {
385*f6dc9357SAndroid Build Coastguard Worker     const UInt32 v = Get32(data + (size_t)i * 4);
386*f6dc9357SAndroid Build Coastguard Worker     if (!IS_CLUSTER_ALLOCATED(v))
387*f6dc9357SAndroid Build Coastguard Worker       continue;
388*f6dc9357SAndroid Build Coastguard Worker     if (v >= numAllocatedBlocks)
389*f6dc9357SAndroid Build Coastguard Worker     {
390*f6dc9357SAndroid Build Coastguard Worker       _unsupported = true;
391*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
392*f6dc9357SAndroid Build Coastguard Worker     }
393*f6dc9357SAndroid Build Coastguard Worker   }
394*f6dc9357SAndroid Build Coastguard Worker 
395*f6dc9357SAndroid Build Coastguard Worker   Stream = stream;
396*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
397*f6dc9357SAndroid Build Coastguard Worker }
398*f6dc9357SAndroid Build Coastguard Worker 
399*f6dc9357SAndroid Build Coastguard Worker 
400*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Close())
401*f6dc9357SAndroid Build Coastguard Worker {
402*f6dc9357SAndroid Build Coastguard Worker   _table.Free();
403*f6dc9357SAndroid Build Coastguard Worker   _phySize = 0;
404*f6dc9357SAndroid Build Coastguard Worker   _isArc = false;
405*f6dc9357SAndroid Build Coastguard Worker   _unsupported = false;
406*f6dc9357SAndroid Build Coastguard Worker 
407*f6dc9357SAndroid Build Coastguard Worker   for (unsigned i = 0; i < kNumGuids; i++)
408*f6dc9357SAndroid Build Coastguard Worker     memset(Guids[i], 0, 16);
409*f6dc9357SAndroid Build Coastguard Worker 
410*f6dc9357SAndroid Build Coastguard Worker   // CHandlerImg:
411*f6dc9357SAndroid Build Coastguard Worker   Clear_HandlerImg_Vars();
412*f6dc9357SAndroid Build Coastguard Worker   Stream.Release();
413*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
414*f6dc9357SAndroid Build Coastguard Worker }
415*f6dc9357SAndroid Build Coastguard Worker 
416*f6dc9357SAndroid Build Coastguard Worker 
417*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetStream(UInt32 /* index */, ISequentialInStream **stream))
418*f6dc9357SAndroid Build Coastguard Worker {
419*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_BEGIN
420*f6dc9357SAndroid Build Coastguard Worker   *stream = NULL;
421*f6dc9357SAndroid Build Coastguard Worker   if (_unsupported)
422*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
423*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<ISequentialInStream> streamTemp = this;
424*f6dc9357SAndroid Build Coastguard Worker   RINOK(InitAndSeek())
425*f6dc9357SAndroid Build Coastguard Worker   *stream = streamTemp.Detach();
426*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
427*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_END
428*f6dc9357SAndroid Build Coastguard Worker }
429*f6dc9357SAndroid Build Coastguard Worker 
430*f6dc9357SAndroid Build Coastguard Worker 
431*f6dc9357SAndroid Build Coastguard Worker REGISTER_ARC_I(
432*f6dc9357SAndroid Build Coastguard Worker   "VDI", "vdi", NULL, 0xC9,
433*f6dc9357SAndroid Build Coastguard Worker   k_Signature,
434*f6dc9357SAndroid Build Coastguard Worker   0x40,
435*f6dc9357SAndroid Build Coastguard Worker   0,
436*f6dc9357SAndroid Build Coastguard Worker   NULL)
437*f6dc9357SAndroid Build Coastguard Worker 
438*f6dc9357SAndroid Build Coastguard Worker }}
439