1*f6dc9357SAndroid Build Coastguard Worker // GptHandler.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/7zCrc.h"
6*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/CpuArch.h"
7*f6dc9357SAndroid Build Coastguard Worker
8*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/ComTry.h"
9*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/IntToString.h"
10*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/MyBuffer.h"
11*f6dc9357SAndroid Build Coastguard Worker
12*f6dc9357SAndroid Build Coastguard Worker #include "../../Windows/PropVariantUtils.h"
13*f6dc9357SAndroid Build Coastguard Worker
14*f6dc9357SAndroid Build Coastguard Worker #include "../Common/RegisterArc.h"
15*f6dc9357SAndroid Build Coastguard Worker #include "../Common/StreamUtils.h"
16*f6dc9357SAndroid Build Coastguard Worker
17*f6dc9357SAndroid Build Coastguard Worker #include "HandlerCont.h"
18*f6dc9357SAndroid Build Coastguard Worker
19*f6dc9357SAndroid Build Coastguard Worker #define Get16(p) GetUi16(p)
20*f6dc9357SAndroid Build Coastguard Worker #define Get32(p) GetUi32(p)
21*f6dc9357SAndroid Build Coastguard Worker #define Get64(p) GetUi64(p)
22*f6dc9357SAndroid Build Coastguard Worker
23*f6dc9357SAndroid Build Coastguard Worker using namespace NWindows;
24*f6dc9357SAndroid Build Coastguard Worker
25*f6dc9357SAndroid Build Coastguard Worker namespace NArchive {
26*f6dc9357SAndroid Build Coastguard Worker
27*f6dc9357SAndroid Build Coastguard Worker namespace NMbr {
28*f6dc9357SAndroid Build Coastguard Worker const char *GetFileSystem(ISequentialInStream *stream, UInt64 partitionSize);
29*f6dc9357SAndroid Build Coastguard Worker }
30*f6dc9357SAndroid Build Coastguard Worker
31*f6dc9357SAndroid Build Coastguard Worker namespace NFat {
32*f6dc9357SAndroid Build Coastguard Worker API_FUNC_IsArc IsArc_Fat(const Byte *p, size_t size);
33*f6dc9357SAndroid Build Coastguard Worker }
34*f6dc9357SAndroid Build Coastguard Worker
35*f6dc9357SAndroid Build Coastguard Worker namespace NGpt {
36*f6dc9357SAndroid Build Coastguard Worker
37*f6dc9357SAndroid Build Coastguard Worker static const unsigned k_SignatureSize = 12;
38*f6dc9357SAndroid Build Coastguard Worker static const Byte k_Signature[k_SignatureSize] =
39*f6dc9357SAndroid Build Coastguard Worker { 'E', 'F', 'I', ' ', 'P', 'A', 'R', 'T', 0, 0, 1, 0 };
40*f6dc9357SAndroid Build Coastguard Worker
41*f6dc9357SAndroid Build Coastguard Worker static const CUInt32PCharPair g_PartitionFlags[] =
42*f6dc9357SAndroid Build Coastguard Worker {
43*f6dc9357SAndroid Build Coastguard Worker { 0, "Sys" },
44*f6dc9357SAndroid Build Coastguard Worker { 1, "Ignore" },
45*f6dc9357SAndroid Build Coastguard Worker { 2, "Legacy" },
46*f6dc9357SAndroid Build Coastguard Worker { 60, "Win-Read-only" },
47*f6dc9357SAndroid Build Coastguard Worker { 62, "Win-Hidden" },
48*f6dc9357SAndroid Build Coastguard Worker { 63, "Win-Not-Automount" }
49*f6dc9357SAndroid Build Coastguard Worker };
50*f6dc9357SAndroid Build Coastguard Worker
51*f6dc9357SAndroid Build Coastguard Worker static const unsigned kNameLen = 36;
52*f6dc9357SAndroid Build Coastguard Worker
53*f6dc9357SAndroid Build Coastguard Worker struct CPartition
54*f6dc9357SAndroid Build Coastguard Worker {
55*f6dc9357SAndroid Build Coastguard Worker Byte Type[16];
56*f6dc9357SAndroid Build Coastguard Worker Byte Id[16];
57*f6dc9357SAndroid Build Coastguard Worker UInt64 FirstLba;
58*f6dc9357SAndroid Build Coastguard Worker UInt64 LastLba;
59*f6dc9357SAndroid Build Coastguard Worker UInt64 Flags;
60*f6dc9357SAndroid Build Coastguard Worker const char *Ext; // detected later
61*f6dc9357SAndroid Build Coastguard Worker Byte Name[kNameLen * 2];
62*f6dc9357SAndroid Build Coastguard Worker
IsUnusedNArchive::NGpt::CPartition63*f6dc9357SAndroid Build Coastguard Worker bool IsUnused() const
64*f6dc9357SAndroid Build Coastguard Worker {
65*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < 16; i++)
66*f6dc9357SAndroid Build Coastguard Worker if (Type[i] != 0)
67*f6dc9357SAndroid Build Coastguard Worker return false;
68*f6dc9357SAndroid Build Coastguard Worker return true;
69*f6dc9357SAndroid Build Coastguard Worker }
70*f6dc9357SAndroid Build Coastguard Worker
GetSizeNArchive::NGpt::CPartition71*f6dc9357SAndroid Build Coastguard Worker UInt64 GetSize(unsigned sectorSizeLog) const { return (LastLba - FirstLba + 1) << sectorSizeLog; }
GetPosNArchive::NGpt::CPartition72*f6dc9357SAndroid Build Coastguard Worker UInt64 GetPos(unsigned sectorSizeLog) const { return FirstLba << sectorSizeLog; }
GetEndNArchive::NGpt::CPartition73*f6dc9357SAndroid Build Coastguard Worker UInt64 GetEnd(unsigned sectorSizeLog) const { return (LastLba + 1) << sectorSizeLog; }
74*f6dc9357SAndroid Build Coastguard Worker
ParseNArchive::NGpt::CPartition75*f6dc9357SAndroid Build Coastguard Worker void Parse(const Byte *p)
76*f6dc9357SAndroid Build Coastguard Worker {
77*f6dc9357SAndroid Build Coastguard Worker memcpy(Type, p, 16);
78*f6dc9357SAndroid Build Coastguard Worker memcpy(Id, p + 16, 16);
79*f6dc9357SAndroid Build Coastguard Worker FirstLba = Get64(p + 32);
80*f6dc9357SAndroid Build Coastguard Worker LastLba = Get64(p + 40);
81*f6dc9357SAndroid Build Coastguard Worker Flags = Get64(p + 48);
82*f6dc9357SAndroid Build Coastguard Worker memcpy(Name, p + 56, kNameLen * 2);
83*f6dc9357SAndroid Build Coastguard Worker Ext = NULL;
84*f6dc9357SAndroid Build Coastguard Worker }
85*f6dc9357SAndroid Build Coastguard Worker };
86*f6dc9357SAndroid Build Coastguard Worker
87*f6dc9357SAndroid Build Coastguard Worker
88*f6dc9357SAndroid Build Coastguard Worker struct CPartType
89*f6dc9357SAndroid Build Coastguard Worker {
90*f6dc9357SAndroid Build Coastguard Worker UInt32 Id;
91*f6dc9357SAndroid Build Coastguard Worker const char *Ext;
92*f6dc9357SAndroid Build Coastguard Worker const char *Type;
93*f6dc9357SAndroid Build Coastguard Worker };
94*f6dc9357SAndroid Build Coastguard Worker
95*f6dc9357SAndroid Build Coastguard Worker static const CPartType kPartTypes[] =
96*f6dc9357SAndroid Build Coastguard Worker {
97*f6dc9357SAndroid Build Coastguard Worker // { 0x0, NULL, "Unused" },
98*f6dc9357SAndroid Build Coastguard Worker
99*f6dc9357SAndroid Build Coastguard Worker { 0x21686148, NULL, "BIOS Boot" },
100*f6dc9357SAndroid Build Coastguard Worker
101*f6dc9357SAndroid Build Coastguard Worker { 0xC12A7328, NULL, "EFI System" },
102*f6dc9357SAndroid Build Coastguard Worker { 0x024DEE41, NULL, "MBR" },
103*f6dc9357SAndroid Build Coastguard Worker
104*f6dc9357SAndroid Build Coastguard Worker { 0xE3C9E316, NULL, "Windows MSR" },
105*f6dc9357SAndroid Build Coastguard Worker { 0xEBD0A0A2, NULL, "Windows BDP" },
106*f6dc9357SAndroid Build Coastguard Worker { 0x5808C8AA, NULL, "Windows LDM Metadata" },
107*f6dc9357SAndroid Build Coastguard Worker { 0xAF9B60A0, NULL, "Windows LDM Data" },
108*f6dc9357SAndroid Build Coastguard Worker { 0xDE94BBA4, NULL, "Windows Recovery" },
109*f6dc9357SAndroid Build Coastguard Worker // { 0x37AFFC90, NULL, "IBM GPFS" },
110*f6dc9357SAndroid Build Coastguard Worker // { 0xE75CAF8F, NULL, "Windows Storage Spaces" },
111*f6dc9357SAndroid Build Coastguard Worker
112*f6dc9357SAndroid Build Coastguard Worker { 0x0FC63DAF, NULL, "Linux Data" },
113*f6dc9357SAndroid Build Coastguard Worker { 0x0657FD6D, NULL, "Linux Swap" },
114*f6dc9357SAndroid Build Coastguard Worker { 0x44479540, NULL, "Linux root (x86)" },
115*f6dc9357SAndroid Build Coastguard Worker { 0x4F68BCE3, NULL, "Linux root (x86-64)" },
116*f6dc9357SAndroid Build Coastguard Worker { 0x69DAD710, NULL, "Linux root (ARM)" },
117*f6dc9357SAndroid Build Coastguard Worker { 0xB921B045, NULL, "Linux root (ARM64)" },
118*f6dc9357SAndroid Build Coastguard Worker { 0x993D8D3D, NULL, "Linux root (IA-64)" },
119*f6dc9357SAndroid Build Coastguard Worker
120*f6dc9357SAndroid Build Coastguard Worker
121*f6dc9357SAndroid Build Coastguard Worker { 0x83BD6B9D, NULL, "FreeBSD Boot" },
122*f6dc9357SAndroid Build Coastguard Worker { 0x516E7CB4, NULL, "FreeBSD Data" },
123*f6dc9357SAndroid Build Coastguard Worker { 0x516E7CB5, NULL, "FreeBSD Swap" },
124*f6dc9357SAndroid Build Coastguard Worker { 0x516E7CB6, "ufs", "FreeBSD UFS" },
125*f6dc9357SAndroid Build Coastguard Worker { 0x516E7CB8, NULL, "FreeBSD Vinum" },
126*f6dc9357SAndroid Build Coastguard Worker { 0x516E7CB8, "zfs", "FreeBSD ZFS" },
127*f6dc9357SAndroid Build Coastguard Worker
128*f6dc9357SAndroid Build Coastguard Worker { 0x48465300, "hfsx", "HFS+" },
129*f6dc9357SAndroid Build Coastguard Worker { 0x7C3457EF, "apfs", "APFS" },
130*f6dc9357SAndroid Build Coastguard Worker };
131*f6dc9357SAndroid Build Coastguard Worker
FindPartType(const Byte * guid)132*f6dc9357SAndroid Build Coastguard Worker static int FindPartType(const Byte *guid)
133*f6dc9357SAndroid Build Coastguard Worker {
134*f6dc9357SAndroid Build Coastguard Worker const UInt32 val = Get32(guid);
135*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < Z7_ARRAY_SIZE(kPartTypes); i++)
136*f6dc9357SAndroid Build Coastguard Worker if (kPartTypes[i].Id == val)
137*f6dc9357SAndroid Build Coastguard Worker return (int)i;
138*f6dc9357SAndroid Build Coastguard Worker return -1;
139*f6dc9357SAndroid Build Coastguard Worker }
140*f6dc9357SAndroid Build Coastguard Worker
141*f6dc9357SAndroid Build Coastguard Worker
RawLeGuidToString_Upper(const Byte * g,char * s)142*f6dc9357SAndroid Build Coastguard Worker static void RawLeGuidToString_Upper(const Byte *g, char *s)
143*f6dc9357SAndroid Build Coastguard Worker {
144*f6dc9357SAndroid Build Coastguard Worker RawLeGuidToString(g, s);
145*f6dc9357SAndroid Build Coastguard Worker // MyStringUpper_Ascii(s);
146*f6dc9357SAndroid Build Coastguard Worker }
147*f6dc9357SAndroid Build Coastguard Worker
148*f6dc9357SAndroid Build Coastguard Worker
149*f6dc9357SAndroid Build Coastguard Worker Z7_class_CHandler_final: public CHandlerCont
150*f6dc9357SAndroid Build Coastguard Worker {
151*f6dc9357SAndroid Build Coastguard Worker Z7_IFACE_COM7_IMP(IInArchive_Cont)
152*f6dc9357SAndroid Build Coastguard Worker
153*f6dc9357SAndroid Build Coastguard Worker CRecordVector<CPartition> _items;
154*f6dc9357SAndroid Build Coastguard Worker UInt64 _totalSize;
155*f6dc9357SAndroid Build Coastguard Worker unsigned _sectorSizeLog;
156*f6dc9357SAndroid Build Coastguard Worker Byte Guid[16];
157*f6dc9357SAndroid Build Coastguard Worker
158*f6dc9357SAndroid Build Coastguard Worker CByteBuffer _buffer;
159*f6dc9357SAndroid Build Coastguard Worker
160*f6dc9357SAndroid Build Coastguard Worker HRESULT Open2(IInStream *stream);
161*f6dc9357SAndroid Build Coastguard Worker
162*f6dc9357SAndroid Build Coastguard Worker virtual int GetItem_ExtractInfo(UInt32 index, UInt64 &pos, UInt64 &size) const Z7_override
163*f6dc9357SAndroid Build Coastguard Worker {
164*f6dc9357SAndroid Build Coastguard Worker const CPartition &item = _items[index];
165*f6dc9357SAndroid Build Coastguard Worker pos = item.GetPos(_sectorSizeLog);
166*f6dc9357SAndroid Build Coastguard Worker size = item.GetSize(_sectorSizeLog);
167*f6dc9357SAndroid Build Coastguard Worker return NExtract::NOperationResult::kOK;
168*f6dc9357SAndroid Build Coastguard Worker }
169*f6dc9357SAndroid Build Coastguard Worker };
170*f6dc9357SAndroid Build Coastguard Worker
171*f6dc9357SAndroid Build Coastguard Worker
172*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::Open2(IInStream *stream)
173*f6dc9357SAndroid Build Coastguard Worker {
174*f6dc9357SAndroid Build Coastguard Worker const unsigned kBufSize = 2 << 12;
175*f6dc9357SAndroid Build Coastguard Worker _buffer.Alloc(kBufSize);
176*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(stream, _buffer, kBufSize))
177*f6dc9357SAndroid Build Coastguard Worker const Byte *buf = _buffer;
178*f6dc9357SAndroid Build Coastguard Worker if (buf[0x1FE] != 0x55 || buf[0x1FF] != 0xAA)
179*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
180*f6dc9357SAndroid Build Coastguard Worker {
181*f6dc9357SAndroid Build Coastguard Worker for (unsigned sectorSizeLog = 9;; sectorSizeLog += 3)
182*f6dc9357SAndroid Build Coastguard Worker {
183*f6dc9357SAndroid Build Coastguard Worker if (sectorSizeLog > 12)
184*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
185*f6dc9357SAndroid Build Coastguard Worker if (memcmp(buf + ((size_t)1 << sectorSizeLog), k_Signature, k_SignatureSize) == 0)
186*f6dc9357SAndroid Build Coastguard Worker {
187*f6dc9357SAndroid Build Coastguard Worker buf += ((size_t)1 << sectorSizeLog);
188*f6dc9357SAndroid Build Coastguard Worker _sectorSizeLog = sectorSizeLog;
189*f6dc9357SAndroid Build Coastguard Worker break;
190*f6dc9357SAndroid Build Coastguard Worker }
191*f6dc9357SAndroid Build Coastguard Worker }
192*f6dc9357SAndroid Build Coastguard Worker }
193*f6dc9357SAndroid Build Coastguard Worker const UInt32 kSectorSize = 1u << _sectorSizeLog;
194*f6dc9357SAndroid Build Coastguard Worker {
195*f6dc9357SAndroid Build Coastguard Worker // if (Get32(buf + 8) != 0x10000) return S_FALSE; // revision
196*f6dc9357SAndroid Build Coastguard Worker const UInt32 headerSize = Get32(buf + 12); // = 0x5C usually
197*f6dc9357SAndroid Build Coastguard Worker if (headerSize > kSectorSize)
198*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
199*f6dc9357SAndroid Build Coastguard Worker const UInt32 crc = Get32(buf + 0x10);
200*f6dc9357SAndroid Build Coastguard Worker SetUi32(_buffer + kSectorSize + 0x10, 0)
201*f6dc9357SAndroid Build Coastguard Worker if (CrcCalc(_buffer + kSectorSize, headerSize) != crc)
202*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
203*f6dc9357SAndroid Build Coastguard Worker }
204*f6dc9357SAndroid Build Coastguard Worker // UInt32 reserved = Get32(buf + 0x14);
205*f6dc9357SAndroid Build Coastguard Worker const UInt64 curLba = Get64(buf + 0x18);
206*f6dc9357SAndroid Build Coastguard Worker if (curLba != 1)
207*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
208*f6dc9357SAndroid Build Coastguard Worker const UInt64 backupLba = Get64(buf + 0x20);
209*f6dc9357SAndroid Build Coastguard Worker // UInt64 firstUsableLba = Get64(buf + 0x28);
210*f6dc9357SAndroid Build Coastguard Worker // UInt64 lastUsableLba = Get64(buf + 0x30);
211*f6dc9357SAndroid Build Coastguard Worker memcpy(Guid, buf + 0x38, 16);
212*f6dc9357SAndroid Build Coastguard Worker const UInt64 tableLba = Get64(buf + 0x48);
213*f6dc9357SAndroid Build Coastguard Worker if (tableLba < 2 || (tableLba >> (63 - _sectorSizeLog)) != 0)
214*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
215*f6dc9357SAndroid Build Coastguard Worker const UInt32 numEntries = Get32(buf + 0x50);
216*f6dc9357SAndroid Build Coastguard Worker if (numEntries > (1 << 16))
217*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
218*f6dc9357SAndroid Build Coastguard Worker const UInt32 entrySize = Get32(buf + 0x54); // = 128 usually
219*f6dc9357SAndroid Build Coastguard Worker if (entrySize < 128 || entrySize > (1 << 12))
220*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
221*f6dc9357SAndroid Build Coastguard Worker const UInt32 entriesCrc = Get32(buf + 0x58);
222*f6dc9357SAndroid Build Coastguard Worker
223*f6dc9357SAndroid Build Coastguard Worker const UInt32 tableSize = entrySize * numEntries;
224*f6dc9357SAndroid Build Coastguard Worker const UInt32 tableSizeAligned = (tableSize + kSectorSize - 1) & ~(kSectorSize - 1);
225*f6dc9357SAndroid Build Coastguard Worker _buffer.Alloc(tableSizeAligned);
226*f6dc9357SAndroid Build Coastguard Worker const UInt64 tableOffset = tableLba * kSectorSize;
227*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekSet(stream, tableOffset))
228*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(stream, _buffer, tableSizeAligned))
229*f6dc9357SAndroid Build Coastguard Worker
230*f6dc9357SAndroid Build Coastguard Worker if (CrcCalc(_buffer, tableSize) != entriesCrc)
231*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
232*f6dc9357SAndroid Build Coastguard Worker
233*f6dc9357SAndroid Build Coastguard Worker _totalSize = tableOffset + tableSizeAligned;
234*f6dc9357SAndroid Build Coastguard Worker
235*f6dc9357SAndroid Build Coastguard Worker for (UInt32 i = 0; i < numEntries; i++)
236*f6dc9357SAndroid Build Coastguard Worker {
237*f6dc9357SAndroid Build Coastguard Worker CPartition item;
238*f6dc9357SAndroid Build Coastguard Worker item.Parse(_buffer + i * entrySize);
239*f6dc9357SAndroid Build Coastguard Worker if (item.IsUnused())
240*f6dc9357SAndroid Build Coastguard Worker continue;
241*f6dc9357SAndroid Build Coastguard Worker if (item.LastLba < item.FirstLba)
242*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
243*f6dc9357SAndroid Build Coastguard Worker if ((item.LastLba >> (63 - _sectorSizeLog)) != 0)
244*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
245*f6dc9357SAndroid Build Coastguard Worker const UInt64 endPos = item.GetEnd(_sectorSizeLog);
246*f6dc9357SAndroid Build Coastguard Worker if (_totalSize < endPos)
247*f6dc9357SAndroid Build Coastguard Worker _totalSize = endPos;
248*f6dc9357SAndroid Build Coastguard Worker _items.Add(item);
249*f6dc9357SAndroid Build Coastguard Worker }
250*f6dc9357SAndroid Build Coastguard Worker
251*f6dc9357SAndroid Build Coastguard Worker _buffer.Free();
252*f6dc9357SAndroid Build Coastguard Worker {
253*f6dc9357SAndroid Build Coastguard Worker if ((backupLba >> (63 - _sectorSizeLog)) != 0)
254*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
255*f6dc9357SAndroid Build Coastguard Worker const UInt64 end = (backupLba + 1) * kSectorSize;
256*f6dc9357SAndroid Build Coastguard Worker if (_totalSize < end)
257*f6dc9357SAndroid Build Coastguard Worker _totalSize = end;
258*f6dc9357SAndroid Build Coastguard Worker }
259*f6dc9357SAndroid Build Coastguard Worker {
260*f6dc9357SAndroid Build Coastguard Worker UInt64 fileEnd;
261*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_GetSize_SeekToEnd(stream, fileEnd))
262*f6dc9357SAndroid Build Coastguard Worker
263*f6dc9357SAndroid Build Coastguard Worker if (_totalSize < fileEnd)
264*f6dc9357SAndroid Build Coastguard Worker {
265*f6dc9357SAndroid Build Coastguard Worker const UInt64 rem = fileEnd - _totalSize;
266*f6dc9357SAndroid Build Coastguard Worker const UInt64 kRemMax = 1 << 22;
267*f6dc9357SAndroid Build Coastguard Worker if (rem <= kRemMax)
268*f6dc9357SAndroid Build Coastguard Worker {
269*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekSet(stream, _totalSize))
270*f6dc9357SAndroid Build Coastguard Worker bool areThereNonZeros = false;
271*f6dc9357SAndroid Build Coastguard Worker UInt64 numZeros = 0;
272*f6dc9357SAndroid Build Coastguard Worker if (ReadZeroTail(stream, areThereNonZeros, numZeros, kRemMax) == S_OK)
273*f6dc9357SAndroid Build Coastguard Worker if (!areThereNonZeros)
274*f6dc9357SAndroid Build Coastguard Worker _totalSize += numZeros;
275*f6dc9357SAndroid Build Coastguard Worker }
276*f6dc9357SAndroid Build Coastguard Worker }
277*f6dc9357SAndroid Build Coastguard Worker }
278*f6dc9357SAndroid Build Coastguard Worker
279*f6dc9357SAndroid Build Coastguard Worker return S_OK;
280*f6dc9357SAndroid Build Coastguard Worker }
281*f6dc9357SAndroid Build Coastguard Worker
282*f6dc9357SAndroid Build Coastguard Worker
283*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Open(IInStream *stream,
284*f6dc9357SAndroid Build Coastguard Worker const UInt64 * /* maxCheckStartPosition */,
285*f6dc9357SAndroid Build Coastguard Worker IArchiveOpenCallback * /* openArchiveCallback */))
286*f6dc9357SAndroid Build Coastguard Worker {
287*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
288*f6dc9357SAndroid Build Coastguard Worker Close();
289*f6dc9357SAndroid Build Coastguard Worker RINOK(Open2(stream))
290*f6dc9357SAndroid Build Coastguard Worker _stream = stream;
291*f6dc9357SAndroid Build Coastguard Worker
292*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (fileIndex, _items)
293*f6dc9357SAndroid Build Coastguard Worker {
294*f6dc9357SAndroid Build Coastguard Worker CPartition &item = _items[fileIndex];
295*f6dc9357SAndroid Build Coastguard Worker const int typeIndex = FindPartType(item.Type);
296*f6dc9357SAndroid Build Coastguard Worker if (typeIndex < 0)
297*f6dc9357SAndroid Build Coastguard Worker continue;
298*f6dc9357SAndroid Build Coastguard Worker const CPartType &t = kPartTypes[(unsigned)typeIndex];
299*f6dc9357SAndroid Build Coastguard Worker if (t.Ext)
300*f6dc9357SAndroid Build Coastguard Worker {
301*f6dc9357SAndroid Build Coastguard Worker item.Ext = t.Ext;
302*f6dc9357SAndroid Build Coastguard Worker continue;
303*f6dc9357SAndroid Build Coastguard Worker }
304*f6dc9357SAndroid Build Coastguard Worker if (t.Type && IsString1PrefixedByString2_NoCase_Ascii(t.Type, "Windows"))
305*f6dc9357SAndroid Build Coastguard Worker {
306*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialInStream> inStream;
307*f6dc9357SAndroid Build Coastguard Worker if (
308*f6dc9357SAndroid Build Coastguard Worker // ((IInArchiveGetStream *)this)->
309*f6dc9357SAndroid Build Coastguard Worker GetStream(fileIndex, &inStream) == S_OK && inStream)
310*f6dc9357SAndroid Build Coastguard Worker {
311*f6dc9357SAndroid Build Coastguard Worker const char *fs = NMbr::GetFileSystem(inStream, item.GetSize(_sectorSizeLog));
312*f6dc9357SAndroid Build Coastguard Worker if (fs)
313*f6dc9357SAndroid Build Coastguard Worker item.Ext = fs;
314*f6dc9357SAndroid Build Coastguard Worker }
315*f6dc9357SAndroid Build Coastguard Worker }
316*f6dc9357SAndroid Build Coastguard Worker }
317*f6dc9357SAndroid Build Coastguard Worker
318*f6dc9357SAndroid Build Coastguard Worker return S_OK;
319*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
320*f6dc9357SAndroid Build Coastguard Worker }
321*f6dc9357SAndroid Build Coastguard Worker
322*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Close())
323*f6dc9357SAndroid Build Coastguard Worker {
324*f6dc9357SAndroid Build Coastguard Worker _sectorSizeLog = 0;
325*f6dc9357SAndroid Build Coastguard Worker _totalSize = 0;
326*f6dc9357SAndroid Build Coastguard Worker memset(Guid, 0, sizeof(Guid));
327*f6dc9357SAndroid Build Coastguard Worker _items.Clear();
328*f6dc9357SAndroid Build Coastguard Worker _stream.Release();
329*f6dc9357SAndroid Build Coastguard Worker return S_OK;
330*f6dc9357SAndroid Build Coastguard Worker }
331*f6dc9357SAndroid Build Coastguard Worker
332*f6dc9357SAndroid Build Coastguard Worker static const Byte kProps[] =
333*f6dc9357SAndroid Build Coastguard Worker {
334*f6dc9357SAndroid Build Coastguard Worker kpidPath,
335*f6dc9357SAndroid Build Coastguard Worker kpidSize,
336*f6dc9357SAndroid Build Coastguard Worker kpidFileSystem,
337*f6dc9357SAndroid Build Coastguard Worker kpidCharacts,
338*f6dc9357SAndroid Build Coastguard Worker kpidOffset,
339*f6dc9357SAndroid Build Coastguard Worker kpidId
340*f6dc9357SAndroid Build Coastguard Worker };
341*f6dc9357SAndroid Build Coastguard Worker
342*f6dc9357SAndroid Build Coastguard Worker static const Byte kArcProps[] =
343*f6dc9357SAndroid Build Coastguard Worker {
344*f6dc9357SAndroid Build Coastguard Worker kpidSectorSize,
345*f6dc9357SAndroid Build Coastguard Worker kpidId
346*f6dc9357SAndroid Build Coastguard Worker };
347*f6dc9357SAndroid Build Coastguard Worker
348*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_Props
349*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_ArcProps
350*f6dc9357SAndroid Build Coastguard Worker
351*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
352*f6dc9357SAndroid Build Coastguard Worker {
353*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
354*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop;
355*f6dc9357SAndroid Build Coastguard Worker switch (propID)
356*f6dc9357SAndroid Build Coastguard Worker {
357*f6dc9357SAndroid Build Coastguard Worker case kpidMainSubfile:
358*f6dc9357SAndroid Build Coastguard Worker {
359*f6dc9357SAndroid Build Coastguard Worker if (_items.Size() == 1)
360*f6dc9357SAndroid Build Coastguard Worker prop = (UInt32)0;
361*f6dc9357SAndroid Build Coastguard Worker break;
362*f6dc9357SAndroid Build Coastguard Worker }
363*f6dc9357SAndroid Build Coastguard Worker case kpidPhySize: prop = _totalSize; break;
364*f6dc9357SAndroid Build Coastguard Worker case kpidSectorSize: prop = (UInt32)((UInt32)1 << _sectorSizeLog); break;
365*f6dc9357SAndroid Build Coastguard Worker case kpidId:
366*f6dc9357SAndroid Build Coastguard Worker {
367*f6dc9357SAndroid Build Coastguard Worker char s[48];
368*f6dc9357SAndroid Build Coastguard Worker RawLeGuidToString_Upper(Guid, s);
369*f6dc9357SAndroid Build Coastguard Worker prop = s;
370*f6dc9357SAndroid Build Coastguard Worker break;
371*f6dc9357SAndroid Build Coastguard Worker }
372*f6dc9357SAndroid Build Coastguard Worker }
373*f6dc9357SAndroid Build Coastguard Worker prop.Detach(value);
374*f6dc9357SAndroid Build Coastguard Worker return S_OK;
375*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
376*f6dc9357SAndroid Build Coastguard Worker }
377*f6dc9357SAndroid Build Coastguard Worker
378*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
379*f6dc9357SAndroid Build Coastguard Worker {
380*f6dc9357SAndroid Build Coastguard Worker *numItems = _items.Size();
381*f6dc9357SAndroid Build Coastguard Worker return S_OK;
382*f6dc9357SAndroid Build Coastguard Worker }
383*f6dc9357SAndroid Build Coastguard Worker
384*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))
385*f6dc9357SAndroid Build Coastguard Worker {
386*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
387*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop;
388*f6dc9357SAndroid Build Coastguard Worker
389*f6dc9357SAndroid Build Coastguard Worker const CPartition &item = _items[index];
390*f6dc9357SAndroid Build Coastguard Worker
391*f6dc9357SAndroid Build Coastguard Worker switch (propID)
392*f6dc9357SAndroid Build Coastguard Worker {
393*f6dc9357SAndroid Build Coastguard Worker case kpidPath:
394*f6dc9357SAndroid Build Coastguard Worker {
395*f6dc9357SAndroid Build Coastguard Worker // Windows BDP partitions can have identical names.
396*f6dc9357SAndroid Build Coastguard Worker // So we add the partition number at front
397*f6dc9357SAndroid Build Coastguard Worker UString s;
398*f6dc9357SAndroid Build Coastguard Worker s.Add_UInt32(index);
399*f6dc9357SAndroid Build Coastguard Worker {
400*f6dc9357SAndroid Build Coastguard Worker UString s2;
401*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < kNameLen; i++)
402*f6dc9357SAndroid Build Coastguard Worker {
403*f6dc9357SAndroid Build Coastguard Worker wchar_t c = (wchar_t)Get16(item.Name + i * 2);
404*f6dc9357SAndroid Build Coastguard Worker if (c == 0)
405*f6dc9357SAndroid Build Coastguard Worker break;
406*f6dc9357SAndroid Build Coastguard Worker s2 += c;
407*f6dc9357SAndroid Build Coastguard Worker }
408*f6dc9357SAndroid Build Coastguard Worker if (!s2.IsEmpty())
409*f6dc9357SAndroid Build Coastguard Worker {
410*f6dc9357SAndroid Build Coastguard Worker s.Add_Dot();
411*f6dc9357SAndroid Build Coastguard Worker s += s2;
412*f6dc9357SAndroid Build Coastguard Worker }
413*f6dc9357SAndroid Build Coastguard Worker }
414*f6dc9357SAndroid Build Coastguard Worker {
415*f6dc9357SAndroid Build Coastguard Worker s.Add_Dot();
416*f6dc9357SAndroid Build Coastguard Worker if (item.Ext)
417*f6dc9357SAndroid Build Coastguard Worker {
418*f6dc9357SAndroid Build Coastguard Worker AString fs (item.Ext);
419*f6dc9357SAndroid Build Coastguard Worker fs.MakeLower_Ascii();
420*f6dc9357SAndroid Build Coastguard Worker s += fs;
421*f6dc9357SAndroid Build Coastguard Worker }
422*f6dc9357SAndroid Build Coastguard Worker else
423*f6dc9357SAndroid Build Coastguard Worker s += "img";
424*f6dc9357SAndroid Build Coastguard Worker }
425*f6dc9357SAndroid Build Coastguard Worker prop = s;
426*f6dc9357SAndroid Build Coastguard Worker break;
427*f6dc9357SAndroid Build Coastguard Worker }
428*f6dc9357SAndroid Build Coastguard Worker
429*f6dc9357SAndroid Build Coastguard Worker case kpidSize:
430*f6dc9357SAndroid Build Coastguard Worker case kpidPackSize: prop = item.GetSize(_sectorSizeLog); break;
431*f6dc9357SAndroid Build Coastguard Worker case kpidOffset: prop = item.GetPos(_sectorSizeLog); break;
432*f6dc9357SAndroid Build Coastguard Worker
433*f6dc9357SAndroid Build Coastguard Worker case kpidFileSystem:
434*f6dc9357SAndroid Build Coastguard Worker {
435*f6dc9357SAndroid Build Coastguard Worker char s[48];
436*f6dc9357SAndroid Build Coastguard Worker const char *res;
437*f6dc9357SAndroid Build Coastguard Worker const int typeIndex = FindPartType(item.Type);
438*f6dc9357SAndroid Build Coastguard Worker if (typeIndex >= 0 && kPartTypes[(unsigned)typeIndex].Type)
439*f6dc9357SAndroid Build Coastguard Worker res = kPartTypes[(unsigned)typeIndex].Type;
440*f6dc9357SAndroid Build Coastguard Worker else
441*f6dc9357SAndroid Build Coastguard Worker {
442*f6dc9357SAndroid Build Coastguard Worker RawLeGuidToString_Upper(item.Type, s);
443*f6dc9357SAndroid Build Coastguard Worker res = s;
444*f6dc9357SAndroid Build Coastguard Worker }
445*f6dc9357SAndroid Build Coastguard Worker prop = res;
446*f6dc9357SAndroid Build Coastguard Worker break;
447*f6dc9357SAndroid Build Coastguard Worker }
448*f6dc9357SAndroid Build Coastguard Worker
449*f6dc9357SAndroid Build Coastguard Worker case kpidId:
450*f6dc9357SAndroid Build Coastguard Worker {
451*f6dc9357SAndroid Build Coastguard Worker char s[48];
452*f6dc9357SAndroid Build Coastguard Worker RawLeGuidToString_Upper(item.Id, s);
453*f6dc9357SAndroid Build Coastguard Worker prop = s;
454*f6dc9357SAndroid Build Coastguard Worker break;
455*f6dc9357SAndroid Build Coastguard Worker }
456*f6dc9357SAndroid Build Coastguard Worker
457*f6dc9357SAndroid Build Coastguard Worker case kpidCharacts: FLAGS64_TO_PROP(g_PartitionFlags, item.Flags, prop); break;
458*f6dc9357SAndroid Build Coastguard Worker }
459*f6dc9357SAndroid Build Coastguard Worker
460*f6dc9357SAndroid Build Coastguard Worker prop.Detach(value);
461*f6dc9357SAndroid Build Coastguard Worker return S_OK;
462*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
463*f6dc9357SAndroid Build Coastguard Worker }
464*f6dc9357SAndroid Build Coastguard Worker
465*f6dc9357SAndroid Build Coastguard Worker // we suppport signature only for 512-bytes sector.
466*f6dc9357SAndroid Build Coastguard Worker REGISTER_ARC_I(
467*f6dc9357SAndroid Build Coastguard Worker "GPT", "gpt mbr", NULL, 0xCB,
468*f6dc9357SAndroid Build Coastguard Worker k_Signature,
469*f6dc9357SAndroid Build Coastguard Worker 1 << 9,
470*f6dc9357SAndroid Build Coastguard Worker 0,
471*f6dc9357SAndroid Build Coastguard Worker NULL)
472*f6dc9357SAndroid Build Coastguard Worker
473*f6dc9357SAndroid Build Coastguard Worker }}
474