1*f6dc9357SAndroid Build Coastguard Worker // VhdHandler.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 "../../../C/CpuArch.h"
6*f6dc9357SAndroid Build Coastguard Worker
7*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/ComTry.h"
8*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/IntToString.h"
9*f6dc9357SAndroid Build Coastguard Worker
10*f6dc9357SAndroid Build Coastguard Worker #include "../../Windows/PropVariant.h"
11*f6dc9357SAndroid Build Coastguard Worker
12*f6dc9357SAndroid Build Coastguard Worker #include "../Common/LimitedStreams.h"
13*f6dc9357SAndroid Build Coastguard Worker #include "../Common/RegisterArc.h"
14*f6dc9357SAndroid Build Coastguard Worker #include "../Common/StreamUtils.h"
15*f6dc9357SAndroid Build Coastguard Worker
16*f6dc9357SAndroid Build Coastguard Worker #include "HandlerCont.h"
17*f6dc9357SAndroid Build Coastguard Worker
18*f6dc9357SAndroid Build Coastguard Worker #define Get16(p) GetBe16(p)
19*f6dc9357SAndroid Build Coastguard Worker #define Get32(p) GetBe32(p)
20*f6dc9357SAndroid Build Coastguard Worker #define Get64(p) GetBe64(p)
21*f6dc9357SAndroid Build Coastguard Worker
22*f6dc9357SAndroid Build Coastguard Worker #define G32(_offs_, dest) dest = Get32(p + (_offs_))
23*f6dc9357SAndroid Build Coastguard Worker #define G64(_offs_, dest) dest = Get64(p + (_offs_))
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 NVhd {
29*f6dc9357SAndroid Build Coastguard Worker
30*f6dc9357SAndroid Build Coastguard Worker static const unsigned kSignatureSize = 10;
31*f6dc9357SAndroid Build Coastguard Worker static const Byte kSignature[kSignatureSize] =
32*f6dc9357SAndroid Build Coastguard Worker { 'c', 'o', 'n', 'e', 'c', 't', 'i', 'x', 0, 0 };
33*f6dc9357SAndroid Build Coastguard Worker
34*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kUnusedBlock = 0xFFFFFFFF;
35*f6dc9357SAndroid Build Coastguard Worker
36*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kDiskType_Fixed = 2;
37*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kDiskType_Dynamic = 3;
38*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kDiskType_Diff = 4;
39*f6dc9357SAndroid Build Coastguard Worker
40*f6dc9357SAndroid Build Coastguard Worker static const char * const kDiskTypes[] =
41*f6dc9357SAndroid Build Coastguard Worker {
42*f6dc9357SAndroid Build Coastguard Worker "0"
43*f6dc9357SAndroid Build Coastguard Worker , "1"
44*f6dc9357SAndroid Build Coastguard Worker , "Fixed"
45*f6dc9357SAndroid Build Coastguard Worker , "Dynamic"
46*f6dc9357SAndroid Build Coastguard Worker , "Differencing"
47*f6dc9357SAndroid Build Coastguard Worker };
48*f6dc9357SAndroid Build Coastguard Worker
49*f6dc9357SAndroid Build Coastguard Worker struct CFooter
50*f6dc9357SAndroid Build Coastguard Worker {
51*f6dc9357SAndroid Build Coastguard Worker // UInt32 Features;
52*f6dc9357SAndroid Build Coastguard Worker // UInt32 FormatVersion;
53*f6dc9357SAndroid Build Coastguard Worker UInt64 DataOffset;
54*f6dc9357SAndroid Build Coastguard Worker UInt32 CTime;
55*f6dc9357SAndroid Build Coastguard Worker UInt32 CreatorApp;
56*f6dc9357SAndroid Build Coastguard Worker UInt32 CreatorVersion;
57*f6dc9357SAndroid Build Coastguard Worker UInt32 CreatorHostOS;
58*f6dc9357SAndroid Build Coastguard Worker // UInt64 OriginalSize;
59*f6dc9357SAndroid Build Coastguard Worker UInt64 CurrentSize;
60*f6dc9357SAndroid Build Coastguard Worker UInt32 DiskGeometry;
61*f6dc9357SAndroid Build Coastguard Worker UInt32 Type;
62*f6dc9357SAndroid Build Coastguard Worker Byte Id[16];
63*f6dc9357SAndroid Build Coastguard Worker Byte SavedState;
64*f6dc9357SAndroid Build Coastguard Worker
IsFixedNArchive::NVhd::CFooter65*f6dc9357SAndroid Build Coastguard Worker bool IsFixed() const { return Type == kDiskType_Fixed; }
ThereIsDynamicNArchive::NVhd::CFooter66*f6dc9357SAndroid Build Coastguard Worker bool ThereIsDynamic() const { return Type == kDiskType_Dynamic || Type == kDiskType_Diff; }
67*f6dc9357SAndroid Build Coastguard Worker // bool IsSupported() const { return Type == kDiskType_Fixed || Type == kDiskType_Dynamic || Type == kDiskType_Diff; }
NumCylsNArchive::NVhd::CFooter68*f6dc9357SAndroid Build Coastguard Worker UInt32 NumCyls() const { return DiskGeometry >> 16; }
NumHeadsNArchive::NVhd::CFooter69*f6dc9357SAndroid Build Coastguard Worker UInt32 NumHeads() const { return (DiskGeometry >> 8) & 0xFF; }
NumSectorsPerTrackNArchive::NVhd::CFooter70*f6dc9357SAndroid Build Coastguard Worker UInt32 NumSectorsPerTrack() const { return DiskGeometry & 0xFF; }
71*f6dc9357SAndroid Build Coastguard Worker void AddTypeString(AString &s) const;
72*f6dc9357SAndroid Build Coastguard Worker bool Parse(const Byte *p);
73*f6dc9357SAndroid Build Coastguard Worker };
74*f6dc9357SAndroid Build Coastguard Worker
AddTypeString(AString & s) const75*f6dc9357SAndroid Build Coastguard Worker void CFooter::AddTypeString(AString &s) const
76*f6dc9357SAndroid Build Coastguard Worker {
77*f6dc9357SAndroid Build Coastguard Worker if (Type < Z7_ARRAY_SIZE(kDiskTypes))
78*f6dc9357SAndroid Build Coastguard Worker s += kDiskTypes[Type];
79*f6dc9357SAndroid Build Coastguard Worker else
80*f6dc9357SAndroid Build Coastguard Worker s.Add_UInt32(Type);
81*f6dc9357SAndroid Build Coastguard Worker }
82*f6dc9357SAndroid Build Coastguard Worker
CheckBlock(const Byte * p,unsigned size,unsigned checkSumOffset,unsigned zeroOffset)83*f6dc9357SAndroid Build Coastguard Worker static bool CheckBlock(const Byte *p, unsigned size, unsigned checkSumOffset, unsigned zeroOffset)
84*f6dc9357SAndroid Build Coastguard Worker {
85*f6dc9357SAndroid Build Coastguard Worker UInt32 sum = 0;
86*f6dc9357SAndroid Build Coastguard Worker unsigned i;
87*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < checkSumOffset; i++)
88*f6dc9357SAndroid Build Coastguard Worker sum += p[i];
89*f6dc9357SAndroid Build Coastguard Worker for (i = checkSumOffset + 4; i < size; i++)
90*f6dc9357SAndroid Build Coastguard Worker sum += p[i];
91*f6dc9357SAndroid Build Coastguard Worker if (~sum != Get32(p + checkSumOffset))
92*f6dc9357SAndroid Build Coastguard Worker return false;
93*f6dc9357SAndroid Build Coastguard Worker for (i = zeroOffset; i < size; i++)
94*f6dc9357SAndroid Build Coastguard Worker if (p[i] != 0)
95*f6dc9357SAndroid Build Coastguard Worker return false;
96*f6dc9357SAndroid Build Coastguard Worker return true;
97*f6dc9357SAndroid Build Coastguard Worker }
98*f6dc9357SAndroid Build Coastguard Worker
99*f6dc9357SAndroid Build Coastguard Worker static const unsigned kSectorSize_Log = 9;
100*f6dc9357SAndroid Build Coastguard Worker static const unsigned kSectorSize = 1 << kSectorSize_Log;
101*f6dc9357SAndroid Build Coastguard Worker static const unsigned kHeaderSize = 512;
102*f6dc9357SAndroid Build Coastguard Worker
Parse(const Byte * p)103*f6dc9357SAndroid Build Coastguard Worker bool CFooter::Parse(const Byte *p)
104*f6dc9357SAndroid Build Coastguard Worker {
105*f6dc9357SAndroid Build Coastguard Worker if (memcmp(p, kSignature, kSignatureSize) != 0)
106*f6dc9357SAndroid Build Coastguard Worker return false;
107*f6dc9357SAndroid Build Coastguard Worker // G32(0x08, Features);
108*f6dc9357SAndroid Build Coastguard Worker // G32(0x0C, FormatVersion);
109*f6dc9357SAndroid Build Coastguard Worker G64(0x10, DataOffset);
110*f6dc9357SAndroid Build Coastguard Worker G32(0x18, CTime);
111*f6dc9357SAndroid Build Coastguard Worker G32(0x1C, CreatorApp);
112*f6dc9357SAndroid Build Coastguard Worker G32(0x20, CreatorVersion);
113*f6dc9357SAndroid Build Coastguard Worker G32(0x24, CreatorHostOS);
114*f6dc9357SAndroid Build Coastguard Worker // G64(0x28, OriginalSize);
115*f6dc9357SAndroid Build Coastguard Worker G64(0x30, CurrentSize);
116*f6dc9357SAndroid Build Coastguard Worker G32(0x38, DiskGeometry);
117*f6dc9357SAndroid Build Coastguard Worker G32(0x3C, Type);
118*f6dc9357SAndroid Build Coastguard Worker if (Type < kDiskType_Fixed ||
119*f6dc9357SAndroid Build Coastguard Worker Type > kDiskType_Diff)
120*f6dc9357SAndroid Build Coastguard Worker return false;
121*f6dc9357SAndroid Build Coastguard Worker memcpy(Id, p + 0x44, 16);
122*f6dc9357SAndroid Build Coastguard Worker SavedState = p[0x54];
123*f6dc9357SAndroid Build Coastguard Worker // if (DataOffset > ((UInt64)1 << 62)) return false;
124*f6dc9357SAndroid Build Coastguard Worker // if (CurrentSize > ((UInt64)1 << 62)) return false;
125*f6dc9357SAndroid Build Coastguard Worker return CheckBlock(p, kHeaderSize, 0x40, 0x55);
126*f6dc9357SAndroid Build Coastguard Worker }
127*f6dc9357SAndroid Build Coastguard Worker
128*f6dc9357SAndroid Build Coastguard Worker struct CParentLocatorEntry
129*f6dc9357SAndroid Build Coastguard Worker {
130*f6dc9357SAndroid Build Coastguard Worker UInt32 Code;
131*f6dc9357SAndroid Build Coastguard Worker UInt32 DataSpace;
132*f6dc9357SAndroid Build Coastguard Worker UInt32 DataLen;
133*f6dc9357SAndroid Build Coastguard Worker UInt64 DataOffset;
134*f6dc9357SAndroid Build Coastguard Worker
ParseNArchive::NVhd::CParentLocatorEntry135*f6dc9357SAndroid Build Coastguard Worker bool Parse(const Byte *p)
136*f6dc9357SAndroid Build Coastguard Worker {
137*f6dc9357SAndroid Build Coastguard Worker G32(0x00, Code);
138*f6dc9357SAndroid Build Coastguard Worker G32(0x04, DataSpace);
139*f6dc9357SAndroid Build Coastguard Worker G32(0x08, DataLen);
140*f6dc9357SAndroid Build Coastguard Worker G64(0x10, DataOffset);
141*f6dc9357SAndroid Build Coastguard Worker return Get32(p + 0x0C) == 0; // Reserved
142*f6dc9357SAndroid Build Coastguard Worker }
143*f6dc9357SAndroid Build Coastguard Worker };
144*f6dc9357SAndroid Build Coastguard Worker
145*f6dc9357SAndroid Build Coastguard Worker struct CDynHeader
146*f6dc9357SAndroid Build Coastguard Worker {
147*f6dc9357SAndroid Build Coastguard Worker // UInt64 DataOffset;
148*f6dc9357SAndroid Build Coastguard Worker UInt64 TableOffset;
149*f6dc9357SAndroid Build Coastguard Worker // UInt32 HeaderVersion;
150*f6dc9357SAndroid Build Coastguard Worker UInt32 NumBlocks;
151*f6dc9357SAndroid Build Coastguard Worker unsigned BlockSizeLog;
152*f6dc9357SAndroid Build Coastguard Worker UInt32 ParentTime;
153*f6dc9357SAndroid Build Coastguard Worker Byte ParentId[16];
154*f6dc9357SAndroid Build Coastguard Worker bool RelativeNameWasUsed;
155*f6dc9357SAndroid Build Coastguard Worker UString ParentName;
156*f6dc9357SAndroid Build Coastguard Worker UString RelativeParentNameFromLocator;
157*f6dc9357SAndroid Build Coastguard Worker CParentLocatorEntry ParentLocators[8];
158*f6dc9357SAndroid Build Coastguard Worker
159*f6dc9357SAndroid Build Coastguard Worker bool Parse(const Byte *p);
NumBitMapSectorsNArchive::NVhd::CDynHeader160*f6dc9357SAndroid Build Coastguard Worker UInt32 NumBitMapSectors() const
161*f6dc9357SAndroid Build Coastguard Worker {
162*f6dc9357SAndroid Build Coastguard Worker UInt32 numSectorsInBlock = (1 << (BlockSizeLog - kSectorSize_Log));
163*f6dc9357SAndroid Build Coastguard Worker return (numSectorsInBlock + kSectorSize * 8 - 1) / (kSectorSize * 8);
164*f6dc9357SAndroid Build Coastguard Worker }
ClearNArchive::NVhd::CDynHeader165*f6dc9357SAndroid Build Coastguard Worker void Clear()
166*f6dc9357SAndroid Build Coastguard Worker {
167*f6dc9357SAndroid Build Coastguard Worker RelativeNameWasUsed = false;
168*f6dc9357SAndroid Build Coastguard Worker ParentName.Empty();
169*f6dc9357SAndroid Build Coastguard Worker RelativeParentNameFromLocator.Empty();
170*f6dc9357SAndroid Build Coastguard Worker }
171*f6dc9357SAndroid Build Coastguard Worker };
172*f6dc9357SAndroid Build Coastguard Worker
Parse(const Byte * p)173*f6dc9357SAndroid Build Coastguard Worker bool CDynHeader::Parse(const Byte *p)
174*f6dc9357SAndroid Build Coastguard Worker {
175*f6dc9357SAndroid Build Coastguard Worker if (memcmp(p, "cxsparse", 8) != 0)
176*f6dc9357SAndroid Build Coastguard Worker return false;
177*f6dc9357SAndroid Build Coastguard Worker // G64(0x08, DataOffset);
178*f6dc9357SAndroid Build Coastguard Worker G64(0x10, TableOffset);
179*f6dc9357SAndroid Build Coastguard Worker // G32(0x18, HeaderVersion);
180*f6dc9357SAndroid Build Coastguard Worker G32(0x1C, NumBlocks);
181*f6dc9357SAndroid Build Coastguard Worker {
182*f6dc9357SAndroid Build Coastguard Worker UInt32 blockSize = Get32(p + 0x20);
183*f6dc9357SAndroid Build Coastguard Worker unsigned i;
184*f6dc9357SAndroid Build Coastguard Worker for (i = kSectorSize_Log;; i++)
185*f6dc9357SAndroid Build Coastguard Worker {
186*f6dc9357SAndroid Build Coastguard Worker if (i > 31)
187*f6dc9357SAndroid Build Coastguard Worker return false;
188*f6dc9357SAndroid Build Coastguard Worker if (((UInt32)1 << i) == blockSize)
189*f6dc9357SAndroid Build Coastguard Worker break;
190*f6dc9357SAndroid Build Coastguard Worker }
191*f6dc9357SAndroid Build Coastguard Worker BlockSizeLog = i;
192*f6dc9357SAndroid Build Coastguard Worker }
193*f6dc9357SAndroid Build Coastguard Worker G32(0x38, ParentTime);
194*f6dc9357SAndroid Build Coastguard Worker if (Get32(p + 0x3C) != 0) // reserved
195*f6dc9357SAndroid Build Coastguard Worker return false;
196*f6dc9357SAndroid Build Coastguard Worker memcpy(ParentId, p + 0x28, 16);
197*f6dc9357SAndroid Build Coastguard Worker {
198*f6dc9357SAndroid Build Coastguard Worker const unsigned kNameLen = 256;
199*f6dc9357SAndroid Build Coastguard Worker wchar_t *s = ParentName.GetBuf(kNameLen);
200*f6dc9357SAndroid Build Coastguard Worker unsigned i;
201*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < kNameLen; i++)
202*f6dc9357SAndroid Build Coastguard Worker {
203*f6dc9357SAndroid Build Coastguard Worker wchar_t c = Get16(p + 0x40 + i * 2);
204*f6dc9357SAndroid Build Coastguard Worker if (c == 0)
205*f6dc9357SAndroid Build Coastguard Worker break;
206*f6dc9357SAndroid Build Coastguard Worker s[i] = c;
207*f6dc9357SAndroid Build Coastguard Worker }
208*f6dc9357SAndroid Build Coastguard Worker s[i] = 0;
209*f6dc9357SAndroid Build Coastguard Worker ParentName.ReleaseBuf_SetLen(i);
210*f6dc9357SAndroid Build Coastguard Worker }
211*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < 8; i++)
212*f6dc9357SAndroid Build Coastguard Worker if (!ParentLocators[i].Parse(p + 0x240 + i * 24))
213*f6dc9357SAndroid Build Coastguard Worker return false;
214*f6dc9357SAndroid Build Coastguard Worker return CheckBlock(p, 1024, 0x24, 0x240 + 8 * 24);
215*f6dc9357SAndroid Build Coastguard Worker }
216*f6dc9357SAndroid Build Coastguard Worker
217*f6dc9357SAndroid Build Coastguard Worker Z7_class_CHandler_final: public CHandlerImg
218*f6dc9357SAndroid Build Coastguard Worker {
219*f6dc9357SAndroid Build Coastguard Worker UInt64 _posInArcLimit;
220*f6dc9357SAndroid Build Coastguard Worker UInt64 _startOffset;
221*f6dc9357SAndroid Build Coastguard Worker UInt64 _phySize;
222*f6dc9357SAndroid Build Coastguard Worker
223*f6dc9357SAndroid Build Coastguard Worker CFooter Footer;
224*f6dc9357SAndroid Build Coastguard Worker CDynHeader Dyn;
225*f6dc9357SAndroid Build Coastguard Worker CRecordVector<UInt32> Bat;
226*f6dc9357SAndroid Build Coastguard Worker CByteBuffer BitMap;
227*f6dc9357SAndroid Build Coastguard Worker UInt32 BitMapTag;
228*f6dc9357SAndroid Build Coastguard Worker UInt32 NumUsedBlocks;
229*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IInStream> ParentStream;
230*f6dc9357SAndroid Build Coastguard Worker CHandler *Parent;
231*f6dc9357SAndroid Build Coastguard Worker UInt64 NumLevels;
232*f6dc9357SAndroid Build Coastguard Worker UString _errorMessage;
233*f6dc9357SAndroid Build Coastguard Worker // bool _unexpectedEnd;
234*f6dc9357SAndroid Build Coastguard Worker
235*f6dc9357SAndroid Build Coastguard Worker void AddErrorMessage(const char *message, const wchar_t *name = NULL)
236*f6dc9357SAndroid Build Coastguard Worker {
237*f6dc9357SAndroid Build Coastguard Worker if (!_errorMessage.IsEmpty())
238*f6dc9357SAndroid Build Coastguard Worker _errorMessage.Add_LF();
239*f6dc9357SAndroid Build Coastguard Worker _errorMessage += message;
240*f6dc9357SAndroid Build Coastguard Worker if (name)
241*f6dc9357SAndroid Build Coastguard Worker _errorMessage += name;
242*f6dc9357SAndroid Build Coastguard Worker }
243*f6dc9357SAndroid Build Coastguard Worker
244*f6dc9357SAndroid Build Coastguard Worker void UpdatePhySize(UInt64 value)
245*f6dc9357SAndroid Build Coastguard Worker {
246*f6dc9357SAndroid Build Coastguard Worker if (_phySize < value)
247*f6dc9357SAndroid Build Coastguard Worker _phySize = value;
248*f6dc9357SAndroid Build Coastguard Worker }
249*f6dc9357SAndroid Build Coastguard Worker
250*f6dc9357SAndroid Build Coastguard Worker HRESULT Seek2(UInt64 offset);
251*f6dc9357SAndroid Build Coastguard Worker HRESULT InitAndSeek();
252*f6dc9357SAndroid Build Coastguard Worker HRESULT ReadPhy(UInt64 offset, void *data, UInt32 size);
253*f6dc9357SAndroid Build Coastguard Worker
254*f6dc9357SAndroid Build Coastguard Worker bool NeedParent() const { return Footer.Type == kDiskType_Diff; }
255*f6dc9357SAndroid Build Coastguard Worker UInt64 GetPackSize() const
256*f6dc9357SAndroid Build Coastguard Worker { return Footer.ThereIsDynamic() ? ((UInt64)NumUsedBlocks << Dyn.BlockSizeLog) : Footer.CurrentSize; }
257*f6dc9357SAndroid Build Coastguard Worker
258*f6dc9357SAndroid Build Coastguard Worker UString GetParentSequence() const
259*f6dc9357SAndroid Build Coastguard Worker {
260*f6dc9357SAndroid Build Coastguard Worker const CHandler *p = this;
261*f6dc9357SAndroid Build Coastguard Worker UString res;
262*f6dc9357SAndroid Build Coastguard Worker while (p && p->NeedParent())
263*f6dc9357SAndroid Build Coastguard Worker {
264*f6dc9357SAndroid Build Coastguard Worker if (!res.IsEmpty())
265*f6dc9357SAndroid Build Coastguard Worker res += " -> ";
266*f6dc9357SAndroid Build Coastguard Worker UString mainName;
267*f6dc9357SAndroid Build Coastguard Worker UString anotherName;
268*f6dc9357SAndroid Build Coastguard Worker if (Dyn.RelativeNameWasUsed)
269*f6dc9357SAndroid Build Coastguard Worker {
270*f6dc9357SAndroid Build Coastguard Worker mainName = p->Dyn.RelativeParentNameFromLocator;
271*f6dc9357SAndroid Build Coastguard Worker anotherName = p->Dyn.ParentName;
272*f6dc9357SAndroid Build Coastguard Worker }
273*f6dc9357SAndroid Build Coastguard Worker else
274*f6dc9357SAndroid Build Coastguard Worker {
275*f6dc9357SAndroid Build Coastguard Worker mainName = p->Dyn.ParentName;
276*f6dc9357SAndroid Build Coastguard Worker anotherName = p->Dyn.RelativeParentNameFromLocator;
277*f6dc9357SAndroid Build Coastguard Worker }
278*f6dc9357SAndroid Build Coastguard Worker res += mainName;
279*f6dc9357SAndroid Build Coastguard Worker if (mainName != anotherName && !anotherName.IsEmpty())
280*f6dc9357SAndroid Build Coastguard Worker {
281*f6dc9357SAndroid Build Coastguard Worker res.Add_Space();
282*f6dc9357SAndroid Build Coastguard Worker res.Add_Char('(');
283*f6dc9357SAndroid Build Coastguard Worker res += anotherName;
284*f6dc9357SAndroid Build Coastguard Worker res.Add_Char(')');
285*f6dc9357SAndroid Build Coastguard Worker }
286*f6dc9357SAndroid Build Coastguard Worker p = p->Parent;
287*f6dc9357SAndroid Build Coastguard Worker }
288*f6dc9357SAndroid Build Coastguard Worker return res;
289*f6dc9357SAndroid Build Coastguard Worker }
290*f6dc9357SAndroid Build Coastguard Worker
291*f6dc9357SAndroid Build Coastguard Worker bool AreParentsOK() const
292*f6dc9357SAndroid Build Coastguard Worker {
293*f6dc9357SAndroid Build Coastguard Worker const CHandler *p = this;
294*f6dc9357SAndroid Build Coastguard Worker while (p->NeedParent())
295*f6dc9357SAndroid Build Coastguard Worker {
296*f6dc9357SAndroid Build Coastguard Worker p = p->Parent;
297*f6dc9357SAndroid Build Coastguard Worker if (!p)
298*f6dc9357SAndroid Build Coastguard Worker return false;
299*f6dc9357SAndroid Build Coastguard Worker }
300*f6dc9357SAndroid Build Coastguard Worker return true;
301*f6dc9357SAndroid Build Coastguard Worker }
302*f6dc9357SAndroid Build Coastguard Worker
303*f6dc9357SAndroid Build Coastguard Worker HRESULT Open3();
304*f6dc9357SAndroid Build Coastguard Worker HRESULT Open2(IInStream *stream, CHandler *child, IArchiveOpenCallback *openArchiveCallback, unsigned level);
305*f6dc9357SAndroid Build Coastguard Worker HRESULT Open2(IInStream *stream, IArchiveOpenCallback *openArchiveCallback) Z7_override
306*f6dc9357SAndroid Build Coastguard Worker {
307*f6dc9357SAndroid Build Coastguard Worker return Open2(stream, NULL, openArchiveCallback, 0);
308*f6dc9357SAndroid Build Coastguard Worker }
309*f6dc9357SAndroid Build Coastguard Worker void CloseAtError() Z7_override;
310*f6dc9357SAndroid Build Coastguard Worker
311*f6dc9357SAndroid Build Coastguard Worker public:
312*f6dc9357SAndroid Build Coastguard Worker Z7_IFACE_COM7_IMP(IInArchive_Img)
313*f6dc9357SAndroid Build Coastguard Worker
314*f6dc9357SAndroid Build Coastguard Worker Z7_IFACE_COM7_IMP(IInArchiveGetStream)
315*f6dc9357SAndroid Build Coastguard Worker Z7_IFACE_COM7_IMP(ISequentialInStream)
316*f6dc9357SAndroid Build Coastguard Worker };
317*f6dc9357SAndroid Build Coastguard Worker
318*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::Seek2(UInt64 offset) { return InStream_SeekSet(Stream, _startOffset + offset); }
319*f6dc9357SAndroid Build Coastguard Worker
320*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::InitAndSeek()
321*f6dc9357SAndroid Build Coastguard Worker {
322*f6dc9357SAndroid Build Coastguard Worker if (ParentStream)
323*f6dc9357SAndroid Build Coastguard Worker {
324*f6dc9357SAndroid Build Coastguard Worker RINOK(Parent->InitAndSeek())
325*f6dc9357SAndroid Build Coastguard Worker }
326*f6dc9357SAndroid Build Coastguard Worker _virtPos = _posInArc = 0;
327*f6dc9357SAndroid Build Coastguard Worker BitMapTag = kUnusedBlock;
328*f6dc9357SAndroid Build Coastguard Worker BitMap.Alloc(Dyn.NumBitMapSectors() << kSectorSize_Log);
329*f6dc9357SAndroid Build Coastguard Worker return Seek2(0);
330*f6dc9357SAndroid Build Coastguard Worker }
331*f6dc9357SAndroid Build Coastguard Worker
332*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::ReadPhy(UInt64 offset, void *data, UInt32 size)
333*f6dc9357SAndroid Build Coastguard Worker {
334*f6dc9357SAndroid Build Coastguard Worker if (offset + size > _posInArcLimit)
335*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
336*f6dc9357SAndroid Build Coastguard Worker if (offset != _posInArc)
337*f6dc9357SAndroid Build Coastguard Worker {
338*f6dc9357SAndroid Build Coastguard Worker _posInArc = offset;
339*f6dc9357SAndroid Build Coastguard Worker RINOK(Seek2(offset))
340*f6dc9357SAndroid Build Coastguard Worker }
341*f6dc9357SAndroid Build Coastguard Worker HRESULT res = ReadStream_FALSE(Stream, data, size);
342*f6dc9357SAndroid Build Coastguard Worker if (res == S_OK)
343*f6dc9357SAndroid Build Coastguard Worker _posInArc += size;
344*f6dc9357SAndroid Build Coastguard Worker else
345*f6dc9357SAndroid Build Coastguard Worker Reset_PosInArc();
346*f6dc9357SAndroid Build Coastguard Worker return res;
347*f6dc9357SAndroid Build Coastguard Worker }
348*f6dc9357SAndroid Build Coastguard Worker
349*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::Open3()
350*f6dc9357SAndroid Build Coastguard Worker {
351*f6dc9357SAndroid Build Coastguard Worker // Fixed archive uses only footer
352*f6dc9357SAndroid Build Coastguard Worker
353*f6dc9357SAndroid Build Coastguard Worker UInt64 startPos;
354*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_GetPos(Stream, startPos))
355*f6dc9357SAndroid Build Coastguard Worker _startOffset = startPos;
356*f6dc9357SAndroid Build Coastguard Worker Byte header[kHeaderSize];
357*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(Stream, header, kHeaderSize))
358*f6dc9357SAndroid Build Coastguard Worker bool headerIsOK = Footer.Parse(header);
359*f6dc9357SAndroid Build Coastguard Worker _size = Footer.CurrentSize;
360*f6dc9357SAndroid Build Coastguard Worker
361*f6dc9357SAndroid Build Coastguard Worker if (headerIsOK && !Footer.ThereIsDynamic())
362*f6dc9357SAndroid Build Coastguard Worker {
363*f6dc9357SAndroid Build Coastguard Worker // fixed archive
364*f6dc9357SAndroid Build Coastguard Worker if (startPos < Footer.CurrentSize)
365*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
366*f6dc9357SAndroid Build Coastguard Worker _posInArcLimit = Footer.CurrentSize;
367*f6dc9357SAndroid Build Coastguard Worker _phySize = Footer.CurrentSize + kHeaderSize;
368*f6dc9357SAndroid Build Coastguard Worker _startOffset = startPos - Footer.CurrentSize;
369*f6dc9357SAndroid Build Coastguard Worker _posInArc = _phySize;
370*f6dc9357SAndroid Build Coastguard Worker return S_OK;
371*f6dc9357SAndroid Build Coastguard Worker }
372*f6dc9357SAndroid Build Coastguard Worker
373*f6dc9357SAndroid Build Coastguard Worker UInt64 fileSize;
374*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_GetSize_SeekToEnd(Stream, fileSize))
375*f6dc9357SAndroid Build Coastguard Worker if (fileSize < kHeaderSize)
376*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
377*f6dc9357SAndroid Build Coastguard Worker
378*f6dc9357SAndroid Build Coastguard Worker const UInt32 kDynSize = 1024;
379*f6dc9357SAndroid Build Coastguard Worker Byte buf[kDynSize];
380*f6dc9357SAndroid Build Coastguard Worker
381*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekSet(Stream, fileSize - kHeaderSize))
382*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(Stream, buf, kHeaderSize))
383*f6dc9357SAndroid Build Coastguard Worker
384*f6dc9357SAndroid Build Coastguard Worker if (!headerIsOK)
385*f6dc9357SAndroid Build Coastguard Worker {
386*f6dc9357SAndroid Build Coastguard Worker if (!Footer.Parse(buf))
387*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
388*f6dc9357SAndroid Build Coastguard Worker _size = Footer.CurrentSize;
389*f6dc9357SAndroid Build Coastguard Worker if (Footer.ThereIsDynamic())
390*f6dc9357SAndroid Build Coastguard Worker return S_FALSE; // we can't open Dynamic Archive backward.
391*f6dc9357SAndroid Build Coastguard Worker // fixed archive
392*f6dc9357SAndroid Build Coastguard Worker _posInArcLimit = Footer.CurrentSize;
393*f6dc9357SAndroid Build Coastguard Worker _phySize = Footer.CurrentSize + kHeaderSize;
394*f6dc9357SAndroid Build Coastguard Worker _startOffset = fileSize - kHeaderSize - Footer.CurrentSize;
395*f6dc9357SAndroid Build Coastguard Worker _posInArc = _phySize;
396*f6dc9357SAndroid Build Coastguard Worker return S_OK;
397*f6dc9357SAndroid Build Coastguard Worker }
398*f6dc9357SAndroid Build Coastguard Worker
399*f6dc9357SAndroid Build Coastguard Worker _phySize = kHeaderSize;
400*f6dc9357SAndroid Build Coastguard Worker _posInArc = fileSize - startPos;
401*f6dc9357SAndroid Build Coastguard Worker _posInArcLimit = _posInArc - kHeaderSize;
402*f6dc9357SAndroid Build Coastguard Worker
403*f6dc9357SAndroid Build Coastguard Worker bool headerAndFooterAreEqual = false;
404*f6dc9357SAndroid Build Coastguard Worker if (memcmp(header, buf, kHeaderSize) == 0)
405*f6dc9357SAndroid Build Coastguard Worker {
406*f6dc9357SAndroid Build Coastguard Worker headerAndFooterAreEqual = true;
407*f6dc9357SAndroid Build Coastguard Worker _phySize = fileSize - _startOffset;
408*f6dc9357SAndroid Build Coastguard Worker }
409*f6dc9357SAndroid Build Coastguard Worker
410*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadPhy(Footer.DataOffset, buf, kDynSize))
411*f6dc9357SAndroid Build Coastguard Worker if (!Dyn.Parse(buf))
412*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
413*f6dc9357SAndroid Build Coastguard Worker
414*f6dc9357SAndroid Build Coastguard Worker UpdatePhySize(Footer.DataOffset + kDynSize);
415*f6dc9357SAndroid Build Coastguard Worker
416*f6dc9357SAndroid Build Coastguard Worker for (int i = 0; i < 8; i++)
417*f6dc9357SAndroid Build Coastguard Worker {
418*f6dc9357SAndroid Build Coastguard Worker const CParentLocatorEntry &locator = Dyn.ParentLocators[i];
419*f6dc9357SAndroid Build Coastguard Worker const UInt32 kNameBufSizeMax = 1024;
420*f6dc9357SAndroid Build Coastguard Worker if (locator.DataLen < kNameBufSizeMax &&
421*f6dc9357SAndroid Build Coastguard Worker locator.DataOffset < _posInArcLimit &&
422*f6dc9357SAndroid Build Coastguard Worker locator.DataOffset + locator.DataLen <= _posInArcLimit)
423*f6dc9357SAndroid Build Coastguard Worker {
424*f6dc9357SAndroid Build Coastguard Worker if (locator.Code == 0x57327275 && (locator.DataLen & 1) == 0)
425*f6dc9357SAndroid Build Coastguard Worker {
426*f6dc9357SAndroid Build Coastguard Worker // "W2ru" locator
427*f6dc9357SAndroid Build Coastguard Worker // Path is encoded as little-endian UTF-16
428*f6dc9357SAndroid Build Coastguard Worker Byte nameBuf[kNameBufSizeMax];
429*f6dc9357SAndroid Build Coastguard Worker UString tempString;
430*f6dc9357SAndroid Build Coastguard Worker unsigned len = (locator.DataLen >> 1);
431*f6dc9357SAndroid Build Coastguard Worker {
432*f6dc9357SAndroid Build Coastguard Worker wchar_t *s = tempString.GetBuf(len);
433*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadPhy(locator.DataOffset, nameBuf, locator.DataLen))
434*f6dc9357SAndroid Build Coastguard Worker unsigned j;
435*f6dc9357SAndroid Build Coastguard Worker for (j = 0; j < len; j++)
436*f6dc9357SAndroid Build Coastguard Worker {
437*f6dc9357SAndroid Build Coastguard Worker wchar_t c = GetUi16(nameBuf + j * 2);
438*f6dc9357SAndroid Build Coastguard Worker if (c == 0)
439*f6dc9357SAndroid Build Coastguard Worker break;
440*f6dc9357SAndroid Build Coastguard Worker s[j] = c;
441*f6dc9357SAndroid Build Coastguard Worker }
442*f6dc9357SAndroid Build Coastguard Worker s[j] = 0;
443*f6dc9357SAndroid Build Coastguard Worker tempString.ReleaseBuf_SetLen(j);
444*f6dc9357SAndroid Build Coastguard Worker }
445*f6dc9357SAndroid Build Coastguard Worker if (tempString[0] == L'.' && tempString[1] == L'\\')
446*f6dc9357SAndroid Build Coastguard Worker tempString.DeleteFrontal(2);
447*f6dc9357SAndroid Build Coastguard Worker Dyn.RelativeParentNameFromLocator = tempString;
448*f6dc9357SAndroid Build Coastguard Worker }
449*f6dc9357SAndroid Build Coastguard Worker }
450*f6dc9357SAndroid Build Coastguard Worker if (locator.DataLen != 0)
451*f6dc9357SAndroid Build Coastguard Worker UpdatePhySize(locator.DataOffset + locator.DataLen);
452*f6dc9357SAndroid Build Coastguard Worker }
453*f6dc9357SAndroid Build Coastguard Worker
454*f6dc9357SAndroid Build Coastguard Worker if (Dyn.NumBlocks >= (UInt32)1 << 31)
455*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
456*f6dc9357SAndroid Build Coastguard Worker if (Footer.CurrentSize == 0)
457*f6dc9357SAndroid Build Coastguard Worker {
458*f6dc9357SAndroid Build Coastguard Worker if (Dyn.NumBlocks != 0)
459*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
460*f6dc9357SAndroid Build Coastguard Worker }
461*f6dc9357SAndroid Build Coastguard Worker else if (((Footer.CurrentSize - 1) >> Dyn.BlockSizeLog) + 1 != Dyn.NumBlocks)
462*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
463*f6dc9357SAndroid Build Coastguard Worker
464*f6dc9357SAndroid Build Coastguard Worker Bat.ClearAndReserve(Dyn.NumBlocks);
465*f6dc9357SAndroid Build Coastguard Worker
466*f6dc9357SAndroid Build Coastguard Worker UInt32 bitmapSize = Dyn.NumBitMapSectors() << kSectorSize_Log;
467*f6dc9357SAndroid Build Coastguard Worker
468*f6dc9357SAndroid Build Coastguard Worker while ((UInt32)Bat.Size() < Dyn.NumBlocks)
469*f6dc9357SAndroid Build Coastguard Worker {
470*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadPhy(Dyn.TableOffset + (UInt64)Bat.Size() * 4, buf, kSectorSize))
471*f6dc9357SAndroid Build Coastguard Worker UpdatePhySize(Dyn.TableOffset + kSectorSize);
472*f6dc9357SAndroid Build Coastguard Worker for (UInt32 j = 0; j < kSectorSize; j += 4)
473*f6dc9357SAndroid Build Coastguard Worker {
474*f6dc9357SAndroid Build Coastguard Worker UInt32 v = Get32(buf + j);
475*f6dc9357SAndroid Build Coastguard Worker if (v != kUnusedBlock)
476*f6dc9357SAndroid Build Coastguard Worker {
477*f6dc9357SAndroid Build Coastguard Worker UInt32 blockSize = (UInt32)1 << Dyn.BlockSizeLog;
478*f6dc9357SAndroid Build Coastguard Worker UpdatePhySize(((UInt64)v << kSectorSize_Log) + bitmapSize + blockSize);
479*f6dc9357SAndroid Build Coastguard Worker NumUsedBlocks++;
480*f6dc9357SAndroid Build Coastguard Worker }
481*f6dc9357SAndroid Build Coastguard Worker Bat.AddInReserved(v);
482*f6dc9357SAndroid Build Coastguard Worker if ((UInt32)Bat.Size() >= Dyn.NumBlocks)
483*f6dc9357SAndroid Build Coastguard Worker break;
484*f6dc9357SAndroid Build Coastguard Worker }
485*f6dc9357SAndroid Build Coastguard Worker }
486*f6dc9357SAndroid Build Coastguard Worker
487*f6dc9357SAndroid Build Coastguard Worker if (headerAndFooterAreEqual)
488*f6dc9357SAndroid Build Coastguard Worker return S_OK;
489*f6dc9357SAndroid Build Coastguard Worker
490*f6dc9357SAndroid Build Coastguard Worker if (_startOffset + _phySize + kHeaderSize > fileSize)
491*f6dc9357SAndroid Build Coastguard Worker {
492*f6dc9357SAndroid Build Coastguard Worker // _unexpectedEnd = true;
493*f6dc9357SAndroid Build Coastguard Worker _posInArcLimit = _phySize;
494*f6dc9357SAndroid Build Coastguard Worker _phySize += kHeaderSize;
495*f6dc9357SAndroid Build Coastguard Worker return S_OK;
496*f6dc9357SAndroid Build Coastguard Worker }
497*f6dc9357SAndroid Build Coastguard Worker
498*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadPhy(_phySize, buf, kHeaderSize))
499*f6dc9357SAndroid Build Coastguard Worker if (memcmp(header, buf, kHeaderSize) == 0)
500*f6dc9357SAndroid Build Coastguard Worker {
501*f6dc9357SAndroid Build Coastguard Worker _posInArcLimit = _phySize;
502*f6dc9357SAndroid Build Coastguard Worker _phySize += kHeaderSize;
503*f6dc9357SAndroid Build Coastguard Worker return S_OK;
504*f6dc9357SAndroid Build Coastguard Worker }
505*f6dc9357SAndroid Build Coastguard Worker
506*f6dc9357SAndroid Build Coastguard Worker if (_phySize == 0x800)
507*f6dc9357SAndroid Build Coastguard Worker {
508*f6dc9357SAndroid Build Coastguard Worker /* WHY does empty archive contain additional empty sector?
509*f6dc9357SAndroid Build Coastguard Worker We skip that sector and check footer again. */
510*f6dc9357SAndroid Build Coastguard Worker unsigned i;
511*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < kSectorSize && buf[i] == 0; i++);
512*f6dc9357SAndroid Build Coastguard Worker if (i == kSectorSize)
513*f6dc9357SAndroid Build Coastguard Worker {
514*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadPhy(_phySize + kSectorSize, buf, kHeaderSize))
515*f6dc9357SAndroid Build Coastguard Worker if (memcmp(header, buf, kHeaderSize) == 0)
516*f6dc9357SAndroid Build Coastguard Worker {
517*f6dc9357SAndroid Build Coastguard Worker _phySize += kSectorSize;
518*f6dc9357SAndroid Build Coastguard Worker _posInArcLimit = _phySize;
519*f6dc9357SAndroid Build Coastguard Worker _phySize += kHeaderSize;
520*f6dc9357SAndroid Build Coastguard Worker return S_OK;
521*f6dc9357SAndroid Build Coastguard Worker }
522*f6dc9357SAndroid Build Coastguard Worker }
523*f6dc9357SAndroid Build Coastguard Worker }
524*f6dc9357SAndroid Build Coastguard Worker _posInArcLimit = _phySize;
525*f6dc9357SAndroid Build Coastguard Worker _phySize += kHeaderSize;
526*f6dc9357SAndroid Build Coastguard Worker AddErrorMessage("Can't find footer");
527*f6dc9357SAndroid Build Coastguard Worker return S_OK;
528*f6dc9357SAndroid Build Coastguard Worker }
529*f6dc9357SAndroid Build Coastguard Worker
530*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Read(void *data, UInt32 size, UInt32 *processedSize))
531*f6dc9357SAndroid Build Coastguard Worker {
532*f6dc9357SAndroid Build Coastguard Worker if (processedSize)
533*f6dc9357SAndroid Build Coastguard Worker *processedSize = 0;
534*f6dc9357SAndroid Build Coastguard Worker if (_virtPos >= Footer.CurrentSize)
535*f6dc9357SAndroid Build Coastguard Worker return S_OK;
536*f6dc9357SAndroid Build Coastguard Worker {
537*f6dc9357SAndroid Build Coastguard Worker const UInt64 rem = Footer.CurrentSize - _virtPos;
538*f6dc9357SAndroid Build Coastguard Worker if (size > rem)
539*f6dc9357SAndroid Build Coastguard Worker size = (UInt32)rem;
540*f6dc9357SAndroid Build Coastguard Worker }
541*f6dc9357SAndroid Build Coastguard Worker if (size == 0)
542*f6dc9357SAndroid Build Coastguard Worker return S_OK;
543*f6dc9357SAndroid Build Coastguard Worker
544*f6dc9357SAndroid Build Coastguard Worker if (Footer.IsFixed())
545*f6dc9357SAndroid Build Coastguard Worker {
546*f6dc9357SAndroid Build Coastguard Worker if (_virtPos > _posInArcLimit)
547*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
548*f6dc9357SAndroid Build Coastguard Worker {
549*f6dc9357SAndroid Build Coastguard Worker const UInt64 rem = _posInArcLimit - _virtPos;
550*f6dc9357SAndroid Build Coastguard Worker if (size > rem)
551*f6dc9357SAndroid Build Coastguard Worker size = (UInt32)rem;
552*f6dc9357SAndroid Build Coastguard Worker }
553*f6dc9357SAndroid Build Coastguard Worker HRESULT res = S_OK;
554*f6dc9357SAndroid Build Coastguard Worker if (_virtPos != _posInArc)
555*f6dc9357SAndroid Build Coastguard Worker {
556*f6dc9357SAndroid Build Coastguard Worker _posInArc = _virtPos;
557*f6dc9357SAndroid Build Coastguard Worker res = Seek2(_virtPos);
558*f6dc9357SAndroid Build Coastguard Worker }
559*f6dc9357SAndroid Build Coastguard Worker if (res == S_OK)
560*f6dc9357SAndroid Build Coastguard Worker {
561*f6dc9357SAndroid Build Coastguard Worker UInt32 processedSize2 = 0;
562*f6dc9357SAndroid Build Coastguard Worker res = Stream->Read(data, size, &processedSize2);
563*f6dc9357SAndroid Build Coastguard Worker if (processedSize)
564*f6dc9357SAndroid Build Coastguard Worker *processedSize = processedSize2;
565*f6dc9357SAndroid Build Coastguard Worker _posInArc += processedSize2;
566*f6dc9357SAndroid Build Coastguard Worker }
567*f6dc9357SAndroid Build Coastguard Worker if (res != S_OK)
568*f6dc9357SAndroid Build Coastguard Worker Reset_PosInArc();
569*f6dc9357SAndroid Build Coastguard Worker return res;
570*f6dc9357SAndroid Build Coastguard Worker }
571*f6dc9357SAndroid Build Coastguard Worker
572*f6dc9357SAndroid Build Coastguard Worker const UInt32 blockIndex = (UInt32)(_virtPos >> Dyn.BlockSizeLog);
573*f6dc9357SAndroid Build Coastguard Worker if (blockIndex >= Bat.Size())
574*f6dc9357SAndroid Build Coastguard Worker return E_FAIL; // it's some unexpected case
575*f6dc9357SAndroid Build Coastguard Worker const UInt32 blockSectIndex = Bat[blockIndex];
576*f6dc9357SAndroid Build Coastguard Worker const UInt32 blockSize = (UInt32)1 << Dyn.BlockSizeLog;
577*f6dc9357SAndroid Build Coastguard Worker UInt32 offsetInBlock = (UInt32)_virtPos & (blockSize - 1);
578*f6dc9357SAndroid Build Coastguard Worker size = MyMin(blockSize - offsetInBlock, size);
579*f6dc9357SAndroid Build Coastguard Worker
580*f6dc9357SAndroid Build Coastguard Worker HRESULT res = S_OK;
581*f6dc9357SAndroid Build Coastguard Worker if (blockSectIndex == kUnusedBlock)
582*f6dc9357SAndroid Build Coastguard Worker {
583*f6dc9357SAndroid Build Coastguard Worker if (ParentStream)
584*f6dc9357SAndroid Build Coastguard Worker {
585*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekSet(ParentStream, _virtPos))
586*f6dc9357SAndroid Build Coastguard Worker res = ParentStream->Read(data, size, &size);
587*f6dc9357SAndroid Build Coastguard Worker }
588*f6dc9357SAndroid Build Coastguard Worker else
589*f6dc9357SAndroid Build Coastguard Worker memset(data, 0, size);
590*f6dc9357SAndroid Build Coastguard Worker }
591*f6dc9357SAndroid Build Coastguard Worker else
592*f6dc9357SAndroid Build Coastguard Worker {
593*f6dc9357SAndroid Build Coastguard Worker const UInt64 newPos = (UInt64)blockSectIndex << kSectorSize_Log;
594*f6dc9357SAndroid Build Coastguard Worker if (BitMapTag != blockIndex)
595*f6dc9357SAndroid Build Coastguard Worker {
596*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadPhy(newPos, BitMap, (UInt32)BitMap.Size()))
597*f6dc9357SAndroid Build Coastguard Worker BitMapTag = blockIndex;
598*f6dc9357SAndroid Build Coastguard Worker }
599*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadPhy(newPos + BitMap.Size() + offsetInBlock, data, size))
600*f6dc9357SAndroid Build Coastguard Worker for (UInt32 cur = 0; cur < size;)
601*f6dc9357SAndroid Build Coastguard Worker {
602*f6dc9357SAndroid Build Coastguard Worker const UInt32 rem = MyMin(0x200 - (offsetInBlock & 0x1FF), size - cur);
603*f6dc9357SAndroid Build Coastguard Worker const UInt32 bmi = offsetInBlock >> kSectorSize_Log;
604*f6dc9357SAndroid Build Coastguard Worker if (((BitMap[bmi >> 3] >> (7 - (bmi & 7))) & 1) == 0)
605*f6dc9357SAndroid Build Coastguard Worker {
606*f6dc9357SAndroid Build Coastguard Worker if (ParentStream)
607*f6dc9357SAndroid Build Coastguard Worker {
608*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekSet(ParentStream, _virtPos + cur))
609*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(ParentStream, (Byte *)data + cur, rem))
610*f6dc9357SAndroid Build Coastguard Worker }
611*f6dc9357SAndroid Build Coastguard Worker else
612*f6dc9357SAndroid Build Coastguard Worker {
613*f6dc9357SAndroid Build Coastguard Worker const Byte *p = (const Byte *)data + cur;
614*f6dc9357SAndroid Build Coastguard Worker for (UInt32 i = 0; i < rem; i++)
615*f6dc9357SAndroid Build Coastguard Worker if (p[i] != 0)
616*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
617*f6dc9357SAndroid Build Coastguard Worker }
618*f6dc9357SAndroid Build Coastguard Worker }
619*f6dc9357SAndroid Build Coastguard Worker offsetInBlock += rem;
620*f6dc9357SAndroid Build Coastguard Worker cur += rem;
621*f6dc9357SAndroid Build Coastguard Worker }
622*f6dc9357SAndroid Build Coastguard Worker }
623*f6dc9357SAndroid Build Coastguard Worker if (processedSize)
624*f6dc9357SAndroid Build Coastguard Worker *processedSize = size;
625*f6dc9357SAndroid Build Coastguard Worker _virtPos += size;
626*f6dc9357SAndroid Build Coastguard Worker return res;
627*f6dc9357SAndroid Build Coastguard Worker }
628*f6dc9357SAndroid Build Coastguard Worker
629*f6dc9357SAndroid Build Coastguard Worker
630*f6dc9357SAndroid Build Coastguard Worker enum
631*f6dc9357SAndroid Build Coastguard Worker {
632*f6dc9357SAndroid Build Coastguard Worker kpidParent = kpidUserDefined,
633*f6dc9357SAndroid Build Coastguard Worker kpidSavedState
634*f6dc9357SAndroid Build Coastguard Worker };
635*f6dc9357SAndroid Build Coastguard Worker
636*f6dc9357SAndroid Build Coastguard Worker static const CStatProp kArcProps[] =
637*f6dc9357SAndroid Build Coastguard Worker {
638*f6dc9357SAndroid Build Coastguard Worker { NULL, kpidOffset, VT_UI8},
639*f6dc9357SAndroid Build Coastguard Worker { NULL, kpidCTime, VT_FILETIME},
640*f6dc9357SAndroid Build Coastguard Worker { NULL, kpidClusterSize, VT_UI8},
641*f6dc9357SAndroid Build Coastguard Worker { NULL, kpidMethod, VT_BSTR},
642*f6dc9357SAndroid Build Coastguard Worker { NULL, kpidNumVolumes, VT_UI4},
643*f6dc9357SAndroid Build Coastguard Worker { NULL, kpidTotalPhySize, VT_UI8},
644*f6dc9357SAndroid Build Coastguard Worker { "Parent", kpidParent, VT_BSTR},
645*f6dc9357SAndroid Build Coastguard Worker { NULL, kpidCreatorApp, VT_BSTR},
646*f6dc9357SAndroid Build Coastguard Worker { NULL, kpidHostOS, VT_BSTR},
647*f6dc9357SAndroid Build Coastguard Worker { "Saved State", kpidSavedState, VT_BOOL},
648*f6dc9357SAndroid Build Coastguard Worker { NULL, kpidId, VT_BSTR}
649*f6dc9357SAndroid Build Coastguard Worker };
650*f6dc9357SAndroid Build Coastguard Worker
651*f6dc9357SAndroid Build Coastguard Worker static const Byte kProps[] =
652*f6dc9357SAndroid Build Coastguard Worker {
653*f6dc9357SAndroid Build Coastguard Worker kpidSize,
654*f6dc9357SAndroid Build Coastguard Worker kpidPackSize,
655*f6dc9357SAndroid Build Coastguard Worker kpidCTime
656*f6dc9357SAndroid Build Coastguard Worker
657*f6dc9357SAndroid Build Coastguard Worker /*
658*f6dc9357SAndroid Build Coastguard Worker { kpidNumCyls, VT_UI4},
659*f6dc9357SAndroid Build Coastguard Worker { kpidNumHeads, VT_UI4},
660*f6dc9357SAndroid Build Coastguard Worker { kpidSectorsPerTrack, VT_UI4}
661*f6dc9357SAndroid Build Coastguard Worker */
662*f6dc9357SAndroid Build Coastguard Worker };
663*f6dc9357SAndroid Build Coastguard Worker
664*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_Props
665*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_ArcProps_WITH_NAME
666*f6dc9357SAndroid Build Coastguard Worker
667*f6dc9357SAndroid Build Coastguard Worker // VHD start time: 2000-01-01
668*f6dc9357SAndroid Build Coastguard Worker static const UInt64 kVhdTimeStartValue = (UInt64)3600 * 24 * (399 * 365 + 24 * 4);
669*f6dc9357SAndroid Build Coastguard Worker
670*f6dc9357SAndroid Build Coastguard Worker static void VhdTimeToFileTime(UInt32 vhdTime, NCOM::CPropVariant &prop)
671*f6dc9357SAndroid Build Coastguard Worker {
672*f6dc9357SAndroid Build Coastguard Worker FILETIME ft, utc;
673*f6dc9357SAndroid Build Coastguard Worker UInt64 v = (kVhdTimeStartValue + vhdTime) * 10000000;
674*f6dc9357SAndroid Build Coastguard Worker ft.dwLowDateTime = (DWORD)v;
675*f6dc9357SAndroid Build Coastguard Worker ft.dwHighDateTime = (DWORD)(v >> 32);
676*f6dc9357SAndroid Build Coastguard Worker // specification says that it's UTC time, but Virtual PC 6 writes local time. Why?
677*f6dc9357SAndroid Build Coastguard Worker LocalFileTimeToFileTime(&ft, &utc);
678*f6dc9357SAndroid Build Coastguard Worker prop = utc;
679*f6dc9357SAndroid Build Coastguard Worker }
680*f6dc9357SAndroid Build Coastguard Worker
681*f6dc9357SAndroid Build Coastguard Worker static void StringToAString(char *dest, UInt32 val)
682*f6dc9357SAndroid Build Coastguard Worker {
683*f6dc9357SAndroid Build Coastguard Worker for (int i = 24; i >= 0; i -= 8)
684*f6dc9357SAndroid Build Coastguard Worker {
685*f6dc9357SAndroid Build Coastguard Worker const Byte b = (Byte)((val >> i) & 0xFF);
686*f6dc9357SAndroid Build Coastguard Worker if (b < 0x20 || b > 0x7F)
687*f6dc9357SAndroid Build Coastguard Worker break;
688*f6dc9357SAndroid Build Coastguard Worker *dest++ = (char)b;
689*f6dc9357SAndroid Build Coastguard Worker }
690*f6dc9357SAndroid Build Coastguard Worker *dest = 0;
691*f6dc9357SAndroid Build Coastguard Worker }
692*f6dc9357SAndroid Build Coastguard Worker
693*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
694*f6dc9357SAndroid Build Coastguard Worker {
695*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
696*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop;
697*f6dc9357SAndroid Build Coastguard Worker switch (propID)
698*f6dc9357SAndroid Build Coastguard Worker {
699*f6dc9357SAndroid Build Coastguard Worker case kpidMainSubfile: prop = (UInt32)0; break;
700*f6dc9357SAndroid Build Coastguard Worker case kpidCTime: VhdTimeToFileTime(Footer.CTime, prop); break;
701*f6dc9357SAndroid Build Coastguard Worker case kpidClusterSize: if (Footer.ThereIsDynamic()) prop = (UInt32)1 << Dyn.BlockSizeLog; break;
702*f6dc9357SAndroid Build Coastguard Worker case kpidShortComment:
703*f6dc9357SAndroid Build Coastguard Worker case kpidMethod:
704*f6dc9357SAndroid Build Coastguard Worker {
705*f6dc9357SAndroid Build Coastguard Worker AString s;
706*f6dc9357SAndroid Build Coastguard Worker Footer.AddTypeString(s);
707*f6dc9357SAndroid Build Coastguard Worker if (NeedParent())
708*f6dc9357SAndroid Build Coastguard Worker {
709*f6dc9357SAndroid Build Coastguard Worker s += " -> ";
710*f6dc9357SAndroid Build Coastguard Worker const CHandler *p = this;
711*f6dc9357SAndroid Build Coastguard Worker while (p && p->NeedParent())
712*f6dc9357SAndroid Build Coastguard Worker p = p->Parent;
713*f6dc9357SAndroid Build Coastguard Worker if (!p)
714*f6dc9357SAndroid Build Coastguard Worker s += '?';
715*f6dc9357SAndroid Build Coastguard Worker else
716*f6dc9357SAndroid Build Coastguard Worker p->Footer.AddTypeString(s);
717*f6dc9357SAndroid Build Coastguard Worker }
718*f6dc9357SAndroid Build Coastguard Worker prop = s;
719*f6dc9357SAndroid Build Coastguard Worker break;
720*f6dc9357SAndroid Build Coastguard Worker }
721*f6dc9357SAndroid Build Coastguard Worker case kpidCreatorApp:
722*f6dc9357SAndroid Build Coastguard Worker {
723*f6dc9357SAndroid Build Coastguard Worker char s[16];
724*f6dc9357SAndroid Build Coastguard Worker StringToAString(s, Footer.CreatorApp);
725*f6dc9357SAndroid Build Coastguard Worker AString res (s);
726*f6dc9357SAndroid Build Coastguard Worker res.Trim();
727*f6dc9357SAndroid Build Coastguard Worker res.Add_Space();
728*f6dc9357SAndroid Build Coastguard Worker res.Add_UInt32(Footer.CreatorVersion >> 16);
729*f6dc9357SAndroid Build Coastguard Worker res.Add_Dot();
730*f6dc9357SAndroid Build Coastguard Worker res.Add_UInt32(Footer.CreatorVersion & 0xFFFF);
731*f6dc9357SAndroid Build Coastguard Worker prop = res;
732*f6dc9357SAndroid Build Coastguard Worker break;
733*f6dc9357SAndroid Build Coastguard Worker }
734*f6dc9357SAndroid Build Coastguard Worker case kpidHostOS:
735*f6dc9357SAndroid Build Coastguard Worker {
736*f6dc9357SAndroid Build Coastguard Worker if (Footer.CreatorHostOS == 0x5769326B)
737*f6dc9357SAndroid Build Coastguard Worker prop = "Windows";
738*f6dc9357SAndroid Build Coastguard Worker else
739*f6dc9357SAndroid Build Coastguard Worker {
740*f6dc9357SAndroid Build Coastguard Worker char s[16];
741*f6dc9357SAndroid Build Coastguard Worker StringToAString(s, Footer.CreatorHostOS);
742*f6dc9357SAndroid Build Coastguard Worker prop = s;
743*f6dc9357SAndroid Build Coastguard Worker }
744*f6dc9357SAndroid Build Coastguard Worker break;
745*f6dc9357SAndroid Build Coastguard Worker }
746*f6dc9357SAndroid Build Coastguard Worker case kpidId:
747*f6dc9357SAndroid Build Coastguard Worker {
748*f6dc9357SAndroid Build Coastguard Worker char s[sizeof(Footer.Id) * 2 + 2];
749*f6dc9357SAndroid Build Coastguard Worker ConvertDataToHex_Upper(s, Footer.Id, sizeof(Footer.Id));
750*f6dc9357SAndroid Build Coastguard Worker prop = s;
751*f6dc9357SAndroid Build Coastguard Worker break;
752*f6dc9357SAndroid Build Coastguard Worker }
753*f6dc9357SAndroid Build Coastguard Worker case kpidSavedState: prop = Footer.SavedState ? true : false; break;
754*f6dc9357SAndroid Build Coastguard Worker case kpidParent: if (NeedParent()) prop = GetParentSequence(); break;
755*f6dc9357SAndroid Build Coastguard Worker case kpidOffset: prop = _startOffset; break;
756*f6dc9357SAndroid Build Coastguard Worker case kpidPhySize: prop = _phySize; break;
757*f6dc9357SAndroid Build Coastguard Worker case kpidTotalPhySize:
758*f6dc9357SAndroid Build Coastguard Worker {
759*f6dc9357SAndroid Build Coastguard Worker const CHandler *p = this;
760*f6dc9357SAndroid Build Coastguard Worker UInt64 sum = 0;
761*f6dc9357SAndroid Build Coastguard Worker do
762*f6dc9357SAndroid Build Coastguard Worker {
763*f6dc9357SAndroid Build Coastguard Worker sum += p->_phySize;
764*f6dc9357SAndroid Build Coastguard Worker p = p->Parent;
765*f6dc9357SAndroid Build Coastguard Worker }
766*f6dc9357SAndroid Build Coastguard Worker while (p);
767*f6dc9357SAndroid Build Coastguard Worker prop = sum;
768*f6dc9357SAndroid Build Coastguard Worker break;
769*f6dc9357SAndroid Build Coastguard Worker }
770*f6dc9357SAndroid Build Coastguard Worker case kpidNumVolumes: if (NumLevels != 1) prop = (UInt32)NumLevels; break;
771*f6dc9357SAndroid Build Coastguard Worker
772*f6dc9357SAndroid Build Coastguard Worker /*
773*f6dc9357SAndroid Build Coastguard Worker case kpidErrorFlags:
774*f6dc9357SAndroid Build Coastguard Worker {
775*f6dc9357SAndroid Build Coastguard Worker UInt32 flags = 0;
776*f6dc9357SAndroid Build Coastguard Worker if (_unexpectedEnd)
777*f6dc9357SAndroid Build Coastguard Worker flags |= kpv_ErrorFlags_UnexpectedEndOfArc;
778*f6dc9357SAndroid Build Coastguard Worker if (flags != 0)
779*f6dc9357SAndroid Build Coastguard Worker prop = flags;
780*f6dc9357SAndroid Build Coastguard Worker break;
781*f6dc9357SAndroid Build Coastguard Worker }
782*f6dc9357SAndroid Build Coastguard Worker */
783*f6dc9357SAndroid Build Coastguard Worker case kpidError: if (!_errorMessage.IsEmpty()) prop = _errorMessage; break;
784*f6dc9357SAndroid Build Coastguard Worker }
785*f6dc9357SAndroid Build Coastguard Worker prop.Detach(value);
786*f6dc9357SAndroid Build Coastguard Worker return S_OK;
787*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
788*f6dc9357SAndroid Build Coastguard Worker }
789*f6dc9357SAndroid Build Coastguard Worker
790*f6dc9357SAndroid Build Coastguard Worker
791*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::Open2(IInStream *stream, CHandler *child, IArchiveOpenCallback *openArchiveCallback, unsigned level)
792*f6dc9357SAndroid Build Coastguard Worker {
793*f6dc9357SAndroid Build Coastguard Worker Close();
794*f6dc9357SAndroid Build Coastguard Worker Stream = stream;
795*f6dc9357SAndroid Build Coastguard Worker if (level > (1 << 12)) // Maybe we need to increase that limit
796*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
797*f6dc9357SAndroid Build Coastguard Worker
798*f6dc9357SAndroid Build Coastguard Worker RINOK(Open3())
799*f6dc9357SAndroid Build Coastguard Worker
800*f6dc9357SAndroid Build Coastguard Worker NumLevels = 1;
801*f6dc9357SAndroid Build Coastguard Worker if (child && memcmp(child->Dyn.ParentId, Footer.Id, 16) != 0)
802*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
803*f6dc9357SAndroid Build Coastguard Worker if (Footer.Type != kDiskType_Diff)
804*f6dc9357SAndroid Build Coastguard Worker return S_OK;
805*f6dc9357SAndroid Build Coastguard Worker
806*f6dc9357SAndroid Build Coastguard Worker bool useRelative;
807*f6dc9357SAndroid Build Coastguard Worker UString name;
808*f6dc9357SAndroid Build Coastguard Worker
809*f6dc9357SAndroid Build Coastguard Worker if (!Dyn.RelativeParentNameFromLocator.IsEmpty())
810*f6dc9357SAndroid Build Coastguard Worker {
811*f6dc9357SAndroid Build Coastguard Worker useRelative = true;
812*f6dc9357SAndroid Build Coastguard Worker name = Dyn.RelativeParentNameFromLocator;
813*f6dc9357SAndroid Build Coastguard Worker }
814*f6dc9357SAndroid Build Coastguard Worker else
815*f6dc9357SAndroid Build Coastguard Worker {
816*f6dc9357SAndroid Build Coastguard Worker useRelative = false;
817*f6dc9357SAndroid Build Coastguard Worker name = Dyn.ParentName;
818*f6dc9357SAndroid Build Coastguard Worker }
819*f6dc9357SAndroid Build Coastguard Worker
820*f6dc9357SAndroid Build Coastguard Worker Dyn.RelativeNameWasUsed = useRelative;
821*f6dc9357SAndroid Build Coastguard Worker
822*f6dc9357SAndroid Build Coastguard Worker Z7_DECL_CMyComPtr_QI_FROM(
823*f6dc9357SAndroid Build Coastguard Worker IArchiveOpenVolumeCallback,
824*f6dc9357SAndroid Build Coastguard Worker openVolumeCallback, openArchiveCallback)
825*f6dc9357SAndroid Build Coastguard Worker
826*f6dc9357SAndroid Build Coastguard Worker if (openVolumeCallback)
827*f6dc9357SAndroid Build Coastguard Worker {
828*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IInStream> nextStream;
829*f6dc9357SAndroid Build Coastguard Worker HRESULT res = openVolumeCallback->GetStream(name, &nextStream);
830*f6dc9357SAndroid Build Coastguard Worker
831*f6dc9357SAndroid Build Coastguard Worker if (res == S_FALSE)
832*f6dc9357SAndroid Build Coastguard Worker {
833*f6dc9357SAndroid Build Coastguard Worker if (useRelative && Dyn.ParentName != Dyn.RelativeParentNameFromLocator)
834*f6dc9357SAndroid Build Coastguard Worker {
835*f6dc9357SAndroid Build Coastguard Worker res = openVolumeCallback->GetStream(Dyn.ParentName, &nextStream);
836*f6dc9357SAndroid Build Coastguard Worker if (res == S_OK)
837*f6dc9357SAndroid Build Coastguard Worker Dyn.RelativeNameWasUsed = false;
838*f6dc9357SAndroid Build Coastguard Worker }
839*f6dc9357SAndroid Build Coastguard Worker }
840*f6dc9357SAndroid Build Coastguard Worker
841*f6dc9357SAndroid Build Coastguard Worker if (res != S_OK && res != S_FALSE)
842*f6dc9357SAndroid Build Coastguard Worker return res;
843*f6dc9357SAndroid Build Coastguard Worker
844*f6dc9357SAndroid Build Coastguard Worker if (res == S_FALSE || !nextStream)
845*f6dc9357SAndroid Build Coastguard Worker {
846*f6dc9357SAndroid Build Coastguard Worker AddErrorMessage("Missing volume : ", name);
847*f6dc9357SAndroid Build Coastguard Worker return S_OK;
848*f6dc9357SAndroid Build Coastguard Worker }
849*f6dc9357SAndroid Build Coastguard Worker
850*f6dc9357SAndroid Build Coastguard Worker Parent = new CHandler;
851*f6dc9357SAndroid Build Coastguard Worker ParentStream = Parent;
852*f6dc9357SAndroid Build Coastguard Worker
853*f6dc9357SAndroid Build Coastguard Worker res = Parent->Open2(nextStream, this, openArchiveCallback, level + 1);
854*f6dc9357SAndroid Build Coastguard Worker
855*f6dc9357SAndroid Build Coastguard Worker if (res != S_OK)
856*f6dc9357SAndroid Build Coastguard Worker {
857*f6dc9357SAndroid Build Coastguard Worker Parent = NULL;
858*f6dc9357SAndroid Build Coastguard Worker ParentStream.Release();
859*f6dc9357SAndroid Build Coastguard Worker if (res == E_ABORT)
860*f6dc9357SAndroid Build Coastguard Worker return res;
861*f6dc9357SAndroid Build Coastguard Worker if (res != S_FALSE)
862*f6dc9357SAndroid Build Coastguard Worker {
863*f6dc9357SAndroid Build Coastguard Worker // we must show that error code
864*f6dc9357SAndroid Build Coastguard Worker }
865*f6dc9357SAndroid Build Coastguard Worker }
866*f6dc9357SAndroid Build Coastguard Worker if (res == S_OK)
867*f6dc9357SAndroid Build Coastguard Worker {
868*f6dc9357SAndroid Build Coastguard Worker NumLevels = Parent->NumLevels + 1;
869*f6dc9357SAndroid Build Coastguard Worker }
870*f6dc9357SAndroid Build Coastguard Worker }
871*f6dc9357SAndroid Build Coastguard Worker {
872*f6dc9357SAndroid Build Coastguard Worker const CHandler *p = this;
873*f6dc9357SAndroid Build Coastguard Worker while (p->NeedParent())
874*f6dc9357SAndroid Build Coastguard Worker {
875*f6dc9357SAndroid Build Coastguard Worker p = p->Parent;
876*f6dc9357SAndroid Build Coastguard Worker if (!p)
877*f6dc9357SAndroid Build Coastguard Worker {
878*f6dc9357SAndroid Build Coastguard Worker AddErrorMessage("Can't open parent VHD file : ", Dyn.ParentName);
879*f6dc9357SAndroid Build Coastguard Worker break;
880*f6dc9357SAndroid Build Coastguard Worker }
881*f6dc9357SAndroid Build Coastguard Worker }
882*f6dc9357SAndroid Build Coastguard Worker }
883*f6dc9357SAndroid Build Coastguard Worker return S_OK;
884*f6dc9357SAndroid Build Coastguard Worker }
885*f6dc9357SAndroid Build Coastguard Worker
886*f6dc9357SAndroid Build Coastguard Worker
887*f6dc9357SAndroid Build Coastguard Worker void CHandler::CloseAtError()
888*f6dc9357SAndroid Build Coastguard Worker {
889*f6dc9357SAndroid Build Coastguard Worker // CHandlerImg:
890*f6dc9357SAndroid Build Coastguard Worker Stream.Release();
891*f6dc9357SAndroid Build Coastguard Worker Clear_HandlerImg_Vars();
892*f6dc9357SAndroid Build Coastguard Worker
893*f6dc9357SAndroid Build Coastguard Worker _phySize = 0;
894*f6dc9357SAndroid Build Coastguard Worker NumLevels = 0;
895*f6dc9357SAndroid Build Coastguard Worker Bat.Clear();
896*f6dc9357SAndroid Build Coastguard Worker NumUsedBlocks = 0;
897*f6dc9357SAndroid Build Coastguard Worker Parent = NULL;
898*f6dc9357SAndroid Build Coastguard Worker ParentStream.Release();
899*f6dc9357SAndroid Build Coastguard Worker Dyn.Clear();
900*f6dc9357SAndroid Build Coastguard Worker _errorMessage.Empty();
901*f6dc9357SAndroid Build Coastguard Worker // _unexpectedEnd = false;
902*f6dc9357SAndroid Build Coastguard Worker }
903*f6dc9357SAndroid Build Coastguard Worker
904*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Close())
905*f6dc9357SAndroid Build Coastguard Worker {
906*f6dc9357SAndroid Build Coastguard Worker CloseAtError();
907*f6dc9357SAndroid Build Coastguard Worker return S_OK;
908*f6dc9357SAndroid Build Coastguard Worker }
909*f6dc9357SAndroid Build Coastguard Worker
910*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value))
911*f6dc9357SAndroid Build Coastguard Worker {
912*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
913*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop;
914*f6dc9357SAndroid Build Coastguard Worker
915*f6dc9357SAndroid Build Coastguard Worker switch (propID)
916*f6dc9357SAndroid Build Coastguard Worker {
917*f6dc9357SAndroid Build Coastguard Worker case kpidSize: prop = Footer.CurrentSize; break;
918*f6dc9357SAndroid Build Coastguard Worker case kpidPackSize: prop = GetPackSize(); break;
919*f6dc9357SAndroid Build Coastguard Worker case kpidCTime: VhdTimeToFileTime(Footer.CTime, prop); break;
920*f6dc9357SAndroid Build Coastguard Worker case kpidExtension: prop = (_imgExt ? _imgExt : "img"); break;
921*f6dc9357SAndroid Build Coastguard Worker
922*f6dc9357SAndroid Build Coastguard Worker /*
923*f6dc9357SAndroid Build Coastguard Worker case kpidNumCyls: prop = Footer.NumCyls(); break;
924*f6dc9357SAndroid Build Coastguard Worker case kpidNumHeads: prop = Footer.NumHeads(); break;
925*f6dc9357SAndroid Build Coastguard Worker case kpidSectorsPerTrack: prop = Footer.NumSectorsPerTrack(); break;
926*f6dc9357SAndroid Build Coastguard Worker */
927*f6dc9357SAndroid Build Coastguard Worker }
928*f6dc9357SAndroid Build Coastguard Worker
929*f6dc9357SAndroid Build Coastguard Worker prop.Detach(value);
930*f6dc9357SAndroid Build Coastguard Worker return S_OK;
931*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
932*f6dc9357SAndroid Build Coastguard Worker }
933*f6dc9357SAndroid Build Coastguard Worker
934*f6dc9357SAndroid Build Coastguard Worker
935*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetStream(UInt32 /* index */, ISequentialInStream **stream))
936*f6dc9357SAndroid Build Coastguard Worker {
937*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
938*f6dc9357SAndroid Build Coastguard Worker *stream = NULL;
939*f6dc9357SAndroid Build Coastguard Worker if (Footer.IsFixed())
940*f6dc9357SAndroid Build Coastguard Worker {
941*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2<ISequentialInStream, CLimitedInStream> streamSpec;
942*f6dc9357SAndroid Build Coastguard Worker streamSpec.Create_if_Empty();
943*f6dc9357SAndroid Build Coastguard Worker streamSpec->SetStream(Stream);
944*f6dc9357SAndroid Build Coastguard Worker // fixme : check (startOffset = 0)
945*f6dc9357SAndroid Build Coastguard Worker streamSpec->InitAndSeek(_startOffset, Footer.CurrentSize);
946*f6dc9357SAndroid Build Coastguard Worker RINOK(streamSpec->SeekToStart())
947*f6dc9357SAndroid Build Coastguard Worker *stream = streamSpec.Detach();
948*f6dc9357SAndroid Build Coastguard Worker return S_OK;
949*f6dc9357SAndroid Build Coastguard Worker }
950*f6dc9357SAndroid Build Coastguard Worker if (!Footer.ThereIsDynamic() || !AreParentsOK())
951*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
952*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialInStream> streamTemp = this;
953*f6dc9357SAndroid Build Coastguard Worker RINOK(InitAndSeek())
954*f6dc9357SAndroid Build Coastguard Worker *stream = streamTemp.Detach();
955*f6dc9357SAndroid Build Coastguard Worker return S_OK;
956*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
957*f6dc9357SAndroid Build Coastguard Worker }
958*f6dc9357SAndroid Build Coastguard Worker
959*f6dc9357SAndroid Build Coastguard Worker REGISTER_ARC_I(
960*f6dc9357SAndroid Build Coastguard Worker "VHD", "vhd", NULL, 0xDC,
961*f6dc9357SAndroid Build Coastguard Worker kSignature,
962*f6dc9357SAndroid Build Coastguard Worker 0,
963*f6dc9357SAndroid Build Coastguard Worker NArcInfoFlags::kUseGlobalOffset,
964*f6dc9357SAndroid Build Coastguard Worker NULL)
965*f6dc9357SAndroid Build Coastguard Worker
966*f6dc9357SAndroid Build Coastguard Worker }}
967