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