xref: /aosp_15_r20/external/lzma/CPP/7zip/Archive/MbrHandler.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker // MbrHandler.cpp
2*f6dc9357SAndroid Build Coastguard Worker 
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker 
5*f6dc9357SAndroid Build Coastguard Worker // #define SHOW_DEBUG_INFO
6*f6dc9357SAndroid Build Coastguard Worker 
7*f6dc9357SAndroid Build Coastguard Worker #ifdef SHOW_DEBUG_INFO
8*f6dc9357SAndroid Build Coastguard Worker #include <stdio.h>
9*f6dc9357SAndroid Build Coastguard Worker #endif
10*f6dc9357SAndroid Build Coastguard Worker 
11*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/CpuArch.h"
12*f6dc9357SAndroid Build Coastguard Worker 
13*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/ComTry.h"
14*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/IntToString.h"
15*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/MyBuffer.h"
16*f6dc9357SAndroid Build Coastguard Worker 
17*f6dc9357SAndroid Build Coastguard Worker #include "../../Windows/PropVariant.h"
18*f6dc9357SAndroid Build Coastguard Worker 
19*f6dc9357SAndroid Build Coastguard Worker #include "../Common/RegisterArc.h"
20*f6dc9357SAndroid Build Coastguard Worker #include "../Common/StreamUtils.h"
21*f6dc9357SAndroid Build Coastguard Worker 
22*f6dc9357SAndroid Build Coastguard Worker #include "HandlerCont.h"
23*f6dc9357SAndroid Build Coastguard Worker 
24*f6dc9357SAndroid Build Coastguard Worker #ifdef SHOW_DEBUG_INFO
25*f6dc9357SAndroid Build Coastguard Worker #define PRF(x) x
26*f6dc9357SAndroid Build Coastguard Worker #else
27*f6dc9357SAndroid Build Coastguard Worker #define PRF(x)
28*f6dc9357SAndroid Build Coastguard Worker #endif
29*f6dc9357SAndroid Build Coastguard Worker 
30*f6dc9357SAndroid Build Coastguard Worker using namespace NWindows;
31*f6dc9357SAndroid Build Coastguard Worker 
32*f6dc9357SAndroid Build Coastguard Worker namespace NArchive {
33*f6dc9357SAndroid Build Coastguard Worker 
34*f6dc9357SAndroid Build Coastguard Worker namespace NFat {
35*f6dc9357SAndroid Build Coastguard Worker API_FUNC_IsArc IsArc_Fat(const Byte *p, size_t size);
36*f6dc9357SAndroid Build Coastguard Worker }
37*f6dc9357SAndroid Build Coastguard Worker 
38*f6dc9357SAndroid Build Coastguard Worker namespace NMbr {
39*f6dc9357SAndroid Build Coastguard Worker 
40*f6dc9357SAndroid Build Coastguard Worker struct CChs
41*f6dc9357SAndroid Build Coastguard Worker {
42*f6dc9357SAndroid Build Coastguard Worker   Byte Head;
43*f6dc9357SAndroid Build Coastguard Worker   Byte SectCyl;
44*f6dc9357SAndroid Build Coastguard Worker   Byte Cyl8;
45*f6dc9357SAndroid Build Coastguard Worker 
GetSectorNArchive::NMbr::CChs46*f6dc9357SAndroid Build Coastguard Worker   UInt32 GetSector() const { return SectCyl & 0x3F; }
GetCylNArchive::NMbr::CChs47*f6dc9357SAndroid Build Coastguard Worker   UInt32 GetCyl() const { return ((UInt32)SectCyl >> 6 << 8) | Cyl8; }
48*f6dc9357SAndroid Build Coastguard Worker   void ToString(NCOM::CPropVariant &prop) const;
49*f6dc9357SAndroid Build Coastguard Worker 
ParseNArchive::NMbr::CChs50*f6dc9357SAndroid Build Coastguard Worker   void Parse(const Byte *p)
51*f6dc9357SAndroid Build Coastguard Worker   {
52*f6dc9357SAndroid Build Coastguard Worker     Head = p[0];
53*f6dc9357SAndroid Build Coastguard Worker     SectCyl = p[1];
54*f6dc9357SAndroid Build Coastguard Worker     Cyl8 = p[2];
55*f6dc9357SAndroid Build Coastguard Worker   }
CheckNArchive::NMbr::CChs56*f6dc9357SAndroid Build Coastguard Worker   bool Check() const { return GetSector() > 0; }
57*f6dc9357SAndroid Build Coastguard Worker };
58*f6dc9357SAndroid Build Coastguard Worker 
59*f6dc9357SAndroid Build Coastguard Worker 
60*f6dc9357SAndroid Build Coastguard Worker // Chs in some MBRs contains only low bits of "Cyl number". So we disable check.
61*f6dc9357SAndroid Build Coastguard Worker /*
62*f6dc9357SAndroid Build Coastguard Worker #define RINOZ(x) { int _t_ = (x); if (_t_ != 0) return _t_; }
63*f6dc9357SAndroid Build Coastguard Worker static int CompareChs(const CChs &c1, const CChs &c2)
64*f6dc9357SAndroid Build Coastguard Worker {
65*f6dc9357SAndroid Build Coastguard Worker   RINOZ(MyCompare(c1.GetCyl(), c2.GetCyl()));
66*f6dc9357SAndroid Build Coastguard Worker   RINOZ(MyCompare(c1.Head, c2.Head));
67*f6dc9357SAndroid Build Coastguard Worker   return MyCompare(c1.GetSector(), c2.GetSector());
68*f6dc9357SAndroid Build Coastguard Worker }
69*f6dc9357SAndroid Build Coastguard Worker */
70*f6dc9357SAndroid Build Coastguard Worker 
ToString(NCOM::CPropVariant & prop) const71*f6dc9357SAndroid Build Coastguard Worker void CChs::ToString(NCOM::CPropVariant &prop) const
72*f6dc9357SAndroid Build Coastguard Worker {
73*f6dc9357SAndroid Build Coastguard Worker   AString s;
74*f6dc9357SAndroid Build Coastguard Worker   s.Add_UInt32(GetCyl());
75*f6dc9357SAndroid Build Coastguard Worker   s.Add_Minus();
76*f6dc9357SAndroid Build Coastguard Worker   s.Add_UInt32(Head);
77*f6dc9357SAndroid Build Coastguard Worker   s.Add_Minus();
78*f6dc9357SAndroid Build Coastguard Worker   s.Add_UInt32(GetSector());
79*f6dc9357SAndroid Build Coastguard Worker   prop = s;
80*f6dc9357SAndroid Build Coastguard Worker }
81*f6dc9357SAndroid Build Coastguard Worker 
82*f6dc9357SAndroid Build Coastguard Worker struct CPartition
83*f6dc9357SAndroid Build Coastguard Worker {
84*f6dc9357SAndroid Build Coastguard Worker   Byte Status;
85*f6dc9357SAndroid Build Coastguard Worker   CChs BeginChs;
86*f6dc9357SAndroid Build Coastguard Worker   Byte Type;
87*f6dc9357SAndroid Build Coastguard Worker   CChs EndChs;
88*f6dc9357SAndroid Build Coastguard Worker   UInt32 Lba;
89*f6dc9357SAndroid Build Coastguard Worker   UInt32 NumBlocks;
90*f6dc9357SAndroid Build Coastguard Worker 
CPartitionNArchive::NMbr::CPartition91*f6dc9357SAndroid Build Coastguard Worker   CPartition() { memset (this, 0, sizeof(*this)); }
92*f6dc9357SAndroid Build Coastguard Worker 
IsEmptyNArchive::NMbr::CPartition93*f6dc9357SAndroid Build Coastguard Worker   bool IsEmpty() const { return Type == 0; }
IsExtendedNArchive::NMbr::CPartition94*f6dc9357SAndroid Build Coastguard Worker   bool IsExtended() const { return Type == 5 || Type == 0xF; }
GetLimitNArchive::NMbr::CPartition95*f6dc9357SAndroid Build Coastguard Worker   UInt32 GetLimit() const { return Lba + NumBlocks; }
96*f6dc9357SAndroid Build Coastguard Worker   // bool IsActive() const { return Status == 0x80; }
GetPosNArchive::NMbr::CPartition97*f6dc9357SAndroid Build Coastguard Worker   UInt64 GetPos(unsigned sectorSizeLog) const { return (UInt64)Lba << sectorSizeLog; }
GetSizeNArchive::NMbr::CPartition98*f6dc9357SAndroid Build Coastguard Worker   UInt64 GetSize(unsigned sectorSizeLog) const { return (UInt64)NumBlocks << sectorSizeLog; }
99*f6dc9357SAndroid Build Coastguard Worker 
CheckLbaLimitsNArchive::NMbr::CPartition100*f6dc9357SAndroid Build Coastguard Worker   bool CheckLbaLimits() const { return (UInt32)0xFFFFFFFF - Lba >= NumBlocks; }
ParseNArchive::NMbr::CPartition101*f6dc9357SAndroid Build Coastguard Worker   bool Parse(const Byte *p)
102*f6dc9357SAndroid Build Coastguard Worker   {
103*f6dc9357SAndroid Build Coastguard Worker     Status = p[0];
104*f6dc9357SAndroid Build Coastguard Worker     BeginChs.Parse(p + 1);
105*f6dc9357SAndroid Build Coastguard Worker     Type = p[4];
106*f6dc9357SAndroid Build Coastguard Worker     EndChs.Parse(p + 5);
107*f6dc9357SAndroid Build Coastguard Worker     Lba = GetUi32(p + 8);
108*f6dc9357SAndroid Build Coastguard Worker     NumBlocks = GetUi32(p + 12);
109*f6dc9357SAndroid Build Coastguard Worker     if (Type == 0)
110*f6dc9357SAndroid Build Coastguard Worker       return true;
111*f6dc9357SAndroid Build Coastguard Worker     if (Status != 0 && Status != 0x80)
112*f6dc9357SAndroid Build Coastguard Worker       return false;
113*f6dc9357SAndroid Build Coastguard Worker     return BeginChs.Check()
114*f6dc9357SAndroid Build Coastguard Worker        && EndChs.Check()
115*f6dc9357SAndroid Build Coastguard Worker        // && CompareChs(BeginChs, EndChs) <= 0
116*f6dc9357SAndroid Build Coastguard Worker        && NumBlocks > 0
117*f6dc9357SAndroid Build Coastguard Worker        && CheckLbaLimits();
118*f6dc9357SAndroid Build Coastguard Worker   }
119*f6dc9357SAndroid Build Coastguard Worker 
120*f6dc9357SAndroid Build Coastguard Worker   #ifdef SHOW_DEBUG_INFO
PrintNArchive::NMbr::CPartition121*f6dc9357SAndroid Build Coastguard Worker   void Print() const
122*f6dc9357SAndroid Build Coastguard Worker   {
123*f6dc9357SAndroid Build Coastguard Worker     NCOM::CPropVariant prop, prop2;
124*f6dc9357SAndroid Build Coastguard Worker     BeginChs.ToString(prop);
125*f6dc9357SAndroid Build Coastguard Worker     EndChs.ToString(prop2);
126*f6dc9357SAndroid Build Coastguard Worker     printf("   %2x %2x %8X %8X %12S %12S", (int)Status, (int)Type, Lba, NumBlocks, prop.bstrVal, prop2.bstrVal);
127*f6dc9357SAndroid Build Coastguard Worker   }
128*f6dc9357SAndroid Build Coastguard Worker   #endif
129*f6dc9357SAndroid Build Coastguard Worker };
130*f6dc9357SAndroid Build Coastguard Worker 
131*f6dc9357SAndroid Build Coastguard Worker struct CPartType
132*f6dc9357SAndroid Build Coastguard Worker {
133*f6dc9357SAndroid Build Coastguard Worker   UInt32 Id;
134*f6dc9357SAndroid Build Coastguard Worker   const char *Ext;
135*f6dc9357SAndroid Build Coastguard Worker   const char *Name;
136*f6dc9357SAndroid Build Coastguard Worker };
137*f6dc9357SAndroid Build Coastguard Worker 
138*f6dc9357SAndroid Build Coastguard Worker #define kFat "fat"
139*f6dc9357SAndroid Build Coastguard Worker 
140*f6dc9357SAndroid Build Coastguard Worker /*
141*f6dc9357SAndroid Build Coastguard Worker if we use "format" command in Windows 10 for existing partition:
142*f6dc9357SAndroid Build Coastguard Worker   - if we format to ExFAT, it sets type=7
143*f6dc9357SAndroid Build Coastguard Worker   - if we format to UDF, it doesn't change type from previous value.
144*f6dc9357SAndroid Build Coastguard Worker */
145*f6dc9357SAndroid Build Coastguard Worker 
146*f6dc9357SAndroid Build Coastguard Worker static const unsigned kType_Windows_NTFS = 7;
147*f6dc9357SAndroid Build Coastguard Worker 
148*f6dc9357SAndroid Build Coastguard Worker static const CPartType kPartTypes[] =
149*f6dc9357SAndroid Build Coastguard Worker {
150*f6dc9357SAndroid Build Coastguard Worker   { 0x01, kFat, "FAT12" },
151*f6dc9357SAndroid Build Coastguard Worker   { 0x04, kFat, "FAT16 DOS 3.0+" },
152*f6dc9357SAndroid Build Coastguard Worker   { 0x05, NULL, "Extended" },
153*f6dc9357SAndroid Build Coastguard Worker   { 0x06, kFat, "FAT16 DOS 3.31+" },
154*f6dc9357SAndroid Build Coastguard Worker   { 0x07, "ntfs", "NTFS" },
155*f6dc9357SAndroid Build Coastguard Worker   { 0x0B, kFat, "FAT32" },
156*f6dc9357SAndroid Build Coastguard Worker   { 0x0C, kFat, "FAT32-LBA" },
157*f6dc9357SAndroid Build Coastguard Worker   { 0x0E, kFat, "FAT16-LBA" },
158*f6dc9357SAndroid Build Coastguard Worker   { 0x0F, NULL, "Extended-LBA" },
159*f6dc9357SAndroid Build Coastguard Worker   { 0x11, kFat, "FAT12-Hidden" },
160*f6dc9357SAndroid Build Coastguard Worker   { 0x14, kFat, "FAT16-Hidden < 32 MB" },
161*f6dc9357SAndroid Build Coastguard Worker   { 0x16, kFat, "FAT16-Hidden >= 32 MB" },
162*f6dc9357SAndroid Build Coastguard Worker   { 0x1B, kFat, "FAT32-Hidden" },
163*f6dc9357SAndroid Build Coastguard Worker   { 0x1C, kFat, "FAT32-LBA-Hidden" },
164*f6dc9357SAndroid Build Coastguard Worker   { 0x1E, kFat, "FAT16-LBA-WIN95-Hidden" },
165*f6dc9357SAndroid Build Coastguard Worker   { 0x27, "ntfs", "NTFS-WinRE" },
166*f6dc9357SAndroid Build Coastguard Worker   { 0x82, NULL, "Solaris x86 / Linux swap" },
167*f6dc9357SAndroid Build Coastguard Worker   { 0x83, NULL, "Linux" },
168*f6dc9357SAndroid Build Coastguard Worker   { 0x8E, "lvm", "Linux LVM" },
169*f6dc9357SAndroid Build Coastguard Worker   { 0xA5, NULL, "BSD slice" },
170*f6dc9357SAndroid Build Coastguard Worker   { 0xBE, NULL, "Solaris 8 boot" },
171*f6dc9357SAndroid Build Coastguard Worker   { 0xBF, NULL, "New Solaris x86" },
172*f6dc9357SAndroid Build Coastguard Worker   { 0xC2, NULL, "Linux-Hidden" },
173*f6dc9357SAndroid Build Coastguard Worker   { 0xC3, NULL, "Linux swap-Hidden" },
174*f6dc9357SAndroid Build Coastguard Worker   { 0xEE, NULL, "GPT" },
175*f6dc9357SAndroid Build Coastguard Worker   { 0xEE, NULL, "EFI" }
176*f6dc9357SAndroid Build Coastguard Worker };
177*f6dc9357SAndroid Build Coastguard Worker 
FindPartType(UInt32 type)178*f6dc9357SAndroid Build Coastguard Worker static int FindPartType(UInt32 type)
179*f6dc9357SAndroid Build Coastguard Worker {
180*f6dc9357SAndroid Build Coastguard Worker   for (unsigned i = 0; i < Z7_ARRAY_SIZE(kPartTypes); i++)
181*f6dc9357SAndroid Build Coastguard Worker     if (kPartTypes[i].Id == type)
182*f6dc9357SAndroid Build Coastguard Worker       return (int)i;
183*f6dc9357SAndroid Build Coastguard Worker   return -1;
184*f6dc9357SAndroid Build Coastguard Worker }
185*f6dc9357SAndroid Build Coastguard Worker 
186*f6dc9357SAndroid Build Coastguard Worker struct CItem
187*f6dc9357SAndroid Build Coastguard Worker {
188*f6dc9357SAndroid Build Coastguard Worker   bool IsReal;
189*f6dc9357SAndroid Build Coastguard Worker   bool IsPrim;
190*f6dc9357SAndroid Build Coastguard Worker   bool WasParsed;
191*f6dc9357SAndroid Build Coastguard Worker   const char *FileSystem;
192*f6dc9357SAndroid Build Coastguard Worker   UInt64 Size;
193*f6dc9357SAndroid Build Coastguard Worker   CPartition Part;
194*f6dc9357SAndroid Build Coastguard Worker 
CItemNArchive::NMbr::CItem195*f6dc9357SAndroid Build Coastguard Worker   CItem():
196*f6dc9357SAndroid Build Coastguard Worker       WasParsed(false),
197*f6dc9357SAndroid Build Coastguard Worker       FileSystem(NULL)
198*f6dc9357SAndroid Build Coastguard Worker       {}
199*f6dc9357SAndroid Build Coastguard Worker };
200*f6dc9357SAndroid Build Coastguard Worker 
201*f6dc9357SAndroid Build Coastguard Worker 
202*f6dc9357SAndroid Build Coastguard Worker Z7_class_CHandler_final: public CHandlerCont
203*f6dc9357SAndroid Build Coastguard Worker {
204*f6dc9357SAndroid Build Coastguard Worker   Z7_IFACE_COM7_IMP(IInArchive_Cont)
205*f6dc9357SAndroid Build Coastguard Worker 
206*f6dc9357SAndroid Build Coastguard Worker   CObjectVector<CItem> _items;
207*f6dc9357SAndroid Build Coastguard Worker   UInt64 _totalSize;
208*f6dc9357SAndroid Build Coastguard Worker   CByteBuffer _buffer;
209*f6dc9357SAndroid Build Coastguard Worker 
210*f6dc9357SAndroid Build Coastguard Worker   UInt32 _signature;
211*f6dc9357SAndroid Build Coastguard Worker   unsigned _sectorSizeLog;
212*f6dc9357SAndroid Build Coastguard Worker 
213*f6dc9357SAndroid Build Coastguard Worker   virtual int GetItem_ExtractInfo(UInt32 index, UInt64 &pos, UInt64 &size) const Z7_override Z7_final
214*f6dc9357SAndroid Build Coastguard Worker   {
215*f6dc9357SAndroid Build Coastguard Worker     const CItem &item = _items[index];
216*f6dc9357SAndroid Build Coastguard Worker     pos = item.Part.GetPos(_sectorSizeLog);
217*f6dc9357SAndroid Build Coastguard Worker     size = item.Size;
218*f6dc9357SAndroid Build Coastguard Worker     return NExtract::NOperationResult::kOK;
219*f6dc9357SAndroid Build Coastguard Worker   }
220*f6dc9357SAndroid Build Coastguard Worker 
221*f6dc9357SAndroid Build Coastguard Worker   HRESULT ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, unsigned level);
222*f6dc9357SAndroid Build Coastguard Worker };
223*f6dc9357SAndroid Build Coastguard Worker 
224*f6dc9357SAndroid Build Coastguard Worker /*
225*f6dc9357SAndroid Build Coastguard Worker static bool IsEmptyBuffer(const Byte *data, size_t size)
226*f6dc9357SAndroid Build Coastguard Worker {
227*f6dc9357SAndroid Build Coastguard Worker   for (unsigned i = 0; i < size; i++)
228*f6dc9357SAndroid Build Coastguard Worker     if (data[i] != 0)
229*f6dc9357SAndroid Build Coastguard Worker       return false;
230*f6dc9357SAndroid Build Coastguard Worker   return true;
231*f6dc9357SAndroid Build Coastguard Worker }
232*f6dc9357SAndroid Build Coastguard Worker */
233*f6dc9357SAndroid Build Coastguard Worker 
234*f6dc9357SAndroid Build Coastguard Worker const char *GetFileSystem(ISequentialInStream *stream, UInt64 partitionSize);
235*f6dc9357SAndroid Build Coastguard Worker 
236*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, unsigned level)
237*f6dc9357SAndroid Build Coastguard Worker {
238*f6dc9357SAndroid Build Coastguard Worker   if (level >= 128 || _items.Size() >= 128)
239*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
240*f6dc9357SAndroid Build Coastguard Worker 
241*f6dc9357SAndroid Build Coastguard Worker   const unsigned kNumHeaderParts = 4;
242*f6dc9357SAndroid Build Coastguard Worker   CPartition parts[kNumHeaderParts];
243*f6dc9357SAndroid Build Coastguard Worker 
244*f6dc9357SAndroid Build Coastguard Worker   if (level == 0)
245*f6dc9357SAndroid Build Coastguard Worker     _sectorSizeLog = 9;
246*f6dc9357SAndroid Build Coastguard Worker   const UInt32 kSectorSize = (UInt32)1 << _sectorSizeLog;
247*f6dc9357SAndroid Build Coastguard Worker   UInt32 bufSize  = kSectorSize;
248*f6dc9357SAndroid Build Coastguard Worker   if (level == 0 && _totalSize >= (1 << 12))
249*f6dc9357SAndroid Build Coastguard Worker     bufSize = (1 << 12);
250*f6dc9357SAndroid Build Coastguard Worker   _buffer.Alloc(bufSize);
251*f6dc9357SAndroid Build Coastguard Worker   {
252*f6dc9357SAndroid Build Coastguard Worker     Byte *buf = _buffer;
253*f6dc9357SAndroid Build Coastguard Worker     const UInt64 newPos = (UInt64)lba << _sectorSizeLog;
254*f6dc9357SAndroid Build Coastguard Worker     if (newPos + bufSize > _totalSize)
255*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
256*f6dc9357SAndroid Build Coastguard Worker     RINOK(InStream_SeekSet(stream, newPos))
257*f6dc9357SAndroid Build Coastguard Worker     RINOK(ReadStream_FALSE(stream, buf, bufSize))
258*f6dc9357SAndroid Build Coastguard Worker     if (buf[0x1FE] != 0x55 || buf[0x1FF] != 0xAA)
259*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
260*f6dc9357SAndroid Build Coastguard Worker     if (level == 0)
261*f6dc9357SAndroid Build Coastguard Worker       _signature = GetUi32(buf + 0x1B8);
262*f6dc9357SAndroid Build Coastguard Worker     for (unsigned i = 0; i < kNumHeaderParts; i++)
263*f6dc9357SAndroid Build Coastguard Worker       if (!parts[i].Parse(buf + 0x1BE + 16 * i))
264*f6dc9357SAndroid Build Coastguard Worker         return S_FALSE;
265*f6dc9357SAndroid Build Coastguard Worker   }
266*f6dc9357SAndroid Build Coastguard Worker 
267*f6dc9357SAndroid Build Coastguard Worker   // 23.02: now we try to detect 4kn format (4 KB sectors case)
268*f6dc9357SAndroid Build Coastguard Worker   if (level == 0)
269*f6dc9357SAndroid Build Coastguard Worker   // if (_totalSize >= (1 << 28)) // we don't expect small images with 4 KB sectors
270*f6dc9357SAndroid Build Coastguard Worker   if (bufSize >= (1 << 12))
271*f6dc9357SAndroid Build Coastguard Worker   {
272*f6dc9357SAndroid Build Coastguard Worker     UInt32 lastLim = 0;
273*f6dc9357SAndroid Build Coastguard Worker     UInt32 firstLba = 0;
274*f6dc9357SAndroid Build Coastguard Worker     UInt32 numBlocks = 0; // in first partition
275*f6dc9357SAndroid Build Coastguard Worker     for (unsigned i = 0; i < kNumHeaderParts; i++)
276*f6dc9357SAndroid Build Coastguard Worker     {
277*f6dc9357SAndroid Build Coastguard Worker       const CPartition &part = parts[i];
278*f6dc9357SAndroid Build Coastguard Worker       if (part.IsEmpty())
279*f6dc9357SAndroid Build Coastguard Worker         continue;
280*f6dc9357SAndroid Build Coastguard Worker       if (firstLba == 0 && part.NumBlocks != 0)
281*f6dc9357SAndroid Build Coastguard Worker       {
282*f6dc9357SAndroid Build Coastguard Worker         firstLba = part.Lba;
283*f6dc9357SAndroid Build Coastguard Worker         numBlocks = part.NumBlocks;
284*f6dc9357SAndroid Build Coastguard Worker       }
285*f6dc9357SAndroid Build Coastguard Worker       const UInt32 newLim = part.GetLimit();
286*f6dc9357SAndroid Build Coastguard Worker       if (newLim < lastLim)
287*f6dc9357SAndroid Build Coastguard Worker         return S_FALSE;
288*f6dc9357SAndroid Build Coastguard Worker       lastLim = newLim;
289*f6dc9357SAndroid Build Coastguard Worker     }
290*f6dc9357SAndroid Build Coastguard Worker     if (lastLim != 0)
291*f6dc9357SAndroid Build Coastguard Worker     {
292*f6dc9357SAndroid Build Coastguard Worker       const UInt64 lim12 = (UInt64)lastLim << 12;
293*f6dc9357SAndroid Build Coastguard Worker       if (lim12 <= _totalSize
294*f6dc9357SAndroid Build Coastguard Worker           // && _totalSize - lim12 < (1 << 28) // we can try to exclude false positive cases
295*f6dc9357SAndroid Build Coastguard Worker           )
296*f6dc9357SAndroid Build Coastguard Worker       // if (IsEmptyBuffer(&_buffer[(1 << 9)], (1 << 12) - (1 << 9)))
297*f6dc9357SAndroid Build Coastguard Worker       if (InStream_SeekSet(stream, (UInt64)firstLba << 12) == S_OK)
298*f6dc9357SAndroid Build Coastguard Worker       if (GetFileSystem(stream, (UInt64)numBlocks << 12))
299*f6dc9357SAndroid Build Coastguard Worker         _sectorSizeLog = 12;
300*f6dc9357SAndroid Build Coastguard Worker     }
301*f6dc9357SAndroid Build Coastguard Worker   }
302*f6dc9357SAndroid Build Coastguard Worker 
303*f6dc9357SAndroid Build Coastguard Worker   PRF(printf("\n# %8X", lba));
304*f6dc9357SAndroid Build Coastguard Worker 
305*f6dc9357SAndroid Build Coastguard Worker   UInt32 limLba = lba + 1;
306*f6dc9357SAndroid Build Coastguard Worker   if (limLba == 0)
307*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
308*f6dc9357SAndroid Build Coastguard Worker 
309*f6dc9357SAndroid Build Coastguard Worker   for (unsigned i = 0; i < kNumHeaderParts; i++)
310*f6dc9357SAndroid Build Coastguard Worker   {
311*f6dc9357SAndroid Build Coastguard Worker     CPartition &part = parts[i];
312*f6dc9357SAndroid Build Coastguard Worker 
313*f6dc9357SAndroid Build Coastguard Worker     if (part.IsEmpty())
314*f6dc9357SAndroid Build Coastguard Worker       continue;
315*f6dc9357SAndroid Build Coastguard Worker     PRF(printf("\n   %2d ", (unsigned)level));
316*f6dc9357SAndroid Build Coastguard Worker     #ifdef SHOW_DEBUG_INFO
317*f6dc9357SAndroid Build Coastguard Worker     part.Print();
318*f6dc9357SAndroid Build Coastguard Worker     #endif
319*f6dc9357SAndroid Build Coastguard Worker 
320*f6dc9357SAndroid Build Coastguard Worker     unsigned numItems = _items.Size();
321*f6dc9357SAndroid Build Coastguard Worker     UInt32 newLba = lba + part.Lba;
322*f6dc9357SAndroid Build Coastguard Worker 
323*f6dc9357SAndroid Build Coastguard Worker     if (part.IsExtended())
324*f6dc9357SAndroid Build Coastguard Worker     {
325*f6dc9357SAndroid Build Coastguard Worker       // if (part.Type == 5) // Check it!
326*f6dc9357SAndroid Build Coastguard Worker       newLba = baseLba + part.Lba;
327*f6dc9357SAndroid Build Coastguard Worker       if (newLba < limLba)
328*f6dc9357SAndroid Build Coastguard Worker         return S_FALSE;
329*f6dc9357SAndroid Build Coastguard Worker       const HRESULT res = ReadTables(stream, level < 1 ? newLba : baseLba, newLba, level + 1);
330*f6dc9357SAndroid Build Coastguard Worker       if (res != S_FALSE && res != S_OK)
331*f6dc9357SAndroid Build Coastguard Worker         return res;
332*f6dc9357SAndroid Build Coastguard Worker     }
333*f6dc9357SAndroid Build Coastguard Worker     if (newLba < limLba)
334*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
335*f6dc9357SAndroid Build Coastguard Worker     part.Lba = newLba;
336*f6dc9357SAndroid Build Coastguard Worker     if (!part.CheckLbaLimits())
337*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
338*f6dc9357SAndroid Build Coastguard Worker 
339*f6dc9357SAndroid Build Coastguard Worker     CItem n;
340*f6dc9357SAndroid Build Coastguard Worker     n.Part = part;
341*f6dc9357SAndroid Build Coastguard Worker     bool addItem = false;
342*f6dc9357SAndroid Build Coastguard Worker     if (numItems == _items.Size())
343*f6dc9357SAndroid Build Coastguard Worker     {
344*f6dc9357SAndroid Build Coastguard Worker       n.IsPrim = (level == 0);
345*f6dc9357SAndroid Build Coastguard Worker       n.IsReal = true;
346*f6dc9357SAndroid Build Coastguard Worker       addItem = true;
347*f6dc9357SAndroid Build Coastguard Worker     }
348*f6dc9357SAndroid Build Coastguard Worker     else
349*f6dc9357SAndroid Build Coastguard Worker     {
350*f6dc9357SAndroid Build Coastguard Worker       const CItem &back = _items.Back();
351*f6dc9357SAndroid Build Coastguard Worker       const UInt32 backLimit = back.Part.GetLimit();
352*f6dc9357SAndroid Build Coastguard Worker       const UInt32 partLimit = part.GetLimit();
353*f6dc9357SAndroid Build Coastguard Worker       if (backLimit < partLimit)
354*f6dc9357SAndroid Build Coastguard Worker       {
355*f6dc9357SAndroid Build Coastguard Worker         n.IsReal = false;
356*f6dc9357SAndroid Build Coastguard Worker         n.Part.Lba = backLimit;
357*f6dc9357SAndroid Build Coastguard Worker         n.Part.NumBlocks = partLimit - backLimit;
358*f6dc9357SAndroid Build Coastguard Worker         addItem = true;
359*f6dc9357SAndroid Build Coastguard Worker       }
360*f6dc9357SAndroid Build Coastguard Worker     }
361*f6dc9357SAndroid Build Coastguard Worker     if (addItem)
362*f6dc9357SAndroid Build Coastguard Worker     {
363*f6dc9357SAndroid Build Coastguard Worker       if (n.Part.GetLimit() < limLba)
364*f6dc9357SAndroid Build Coastguard Worker         return S_FALSE;
365*f6dc9357SAndroid Build Coastguard Worker       limLba = n.Part.GetLimit();
366*f6dc9357SAndroid Build Coastguard Worker       n.Size = n.Part.GetSize(_sectorSizeLog);
367*f6dc9357SAndroid Build Coastguard Worker       _items.Add(n);
368*f6dc9357SAndroid Build Coastguard Worker     }
369*f6dc9357SAndroid Build Coastguard Worker   }
370*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
371*f6dc9357SAndroid Build Coastguard Worker }
372*f6dc9357SAndroid Build Coastguard Worker 
373*f6dc9357SAndroid Build Coastguard Worker 
374*f6dc9357SAndroid Build Coastguard Worker static const Byte k_Ntfs_Signature[] = { 'N', 'T', 'F', 'S', ' ', ' ', ' ', ' ', 0 };
375*f6dc9357SAndroid Build Coastguard Worker 
376*f6dc9357SAndroid Build Coastguard Worker static bool Is_Ntfs(const Byte *p)
377*f6dc9357SAndroid Build Coastguard Worker {
378*f6dc9357SAndroid Build Coastguard Worker   if (p[0x1FE] != 0x55 || p[0x1FF] != 0xAA)
379*f6dc9357SAndroid Build Coastguard Worker     return false;
380*f6dc9357SAndroid Build Coastguard Worker   switch (p[0])
381*f6dc9357SAndroid Build Coastguard Worker   {
382*f6dc9357SAndroid Build Coastguard Worker     case 0xE9: /* codeOffset = 3 + (Int16)Get16(p + 1); */ break;
383*f6dc9357SAndroid Build Coastguard Worker     case 0xEB: if (p[2] != 0x90) return false; /* codeOffset = 2 + (int)(signed char)p[1]; */ break;
384*f6dc9357SAndroid Build Coastguard Worker     default: return false;
385*f6dc9357SAndroid Build Coastguard Worker   }
386*f6dc9357SAndroid Build Coastguard Worker   return memcmp(p + 3, k_Ntfs_Signature, Z7_ARRAY_SIZE(k_Ntfs_Signature)) == 0;
387*f6dc9357SAndroid Build Coastguard Worker }
388*f6dc9357SAndroid Build Coastguard Worker 
389*f6dc9357SAndroid Build Coastguard Worker static const Byte k_ExFat_Signature[] = { 'E', 'X', 'F', 'A', 'T', ' ', ' ', ' ' };
390*f6dc9357SAndroid Build Coastguard Worker 
391*f6dc9357SAndroid Build Coastguard Worker static bool Is_ExFat(const Byte *p)
392*f6dc9357SAndroid Build Coastguard Worker {
393*f6dc9357SAndroid Build Coastguard Worker   if (p[0x1FE] != 0x55 || p[0x1FF] != 0xAA)
394*f6dc9357SAndroid Build Coastguard Worker     return false;
395*f6dc9357SAndroid Build Coastguard Worker   if (p[0] != 0xEB || p[1] != 0x76 || p[2] != 0x90)
396*f6dc9357SAndroid Build Coastguard Worker     return false;
397*f6dc9357SAndroid Build Coastguard Worker   return memcmp(p + 3, k_ExFat_Signature, Z7_ARRAY_SIZE(k_ExFat_Signature)) == 0;
398*f6dc9357SAndroid Build Coastguard Worker }
399*f6dc9357SAndroid Build Coastguard Worker 
400*f6dc9357SAndroid Build Coastguard Worker static bool AllAreZeros(const Byte *p, size_t size)
401*f6dc9357SAndroid Build Coastguard Worker {
402*f6dc9357SAndroid Build Coastguard Worker   for (size_t i = 0; i < size; i++)
403*f6dc9357SAndroid Build Coastguard Worker     if (p[i] != 0)
404*f6dc9357SAndroid Build Coastguard Worker       return false;
405*f6dc9357SAndroid Build Coastguard Worker   return true;
406*f6dc9357SAndroid Build Coastguard Worker }
407*f6dc9357SAndroid Build Coastguard Worker 
408*f6dc9357SAndroid Build Coastguard Worker static const UInt32 k_Udf_StartPos = 0x8000;
409*f6dc9357SAndroid Build Coastguard Worker static const Byte k_Udf_Signature[] = { 0, 'B', 'E', 'A', '0', '1', 1, 0 };
410*f6dc9357SAndroid Build Coastguard Worker 
411*f6dc9357SAndroid Build Coastguard Worker static bool Is_Udf(const Byte *p)
412*f6dc9357SAndroid Build Coastguard Worker {
413*f6dc9357SAndroid Build Coastguard Worker   return memcmp(p + k_Udf_StartPos, k_Udf_Signature, sizeof(k_Udf_Signature)) == 0;
414*f6dc9357SAndroid Build Coastguard Worker }
415*f6dc9357SAndroid Build Coastguard Worker 
416*f6dc9357SAndroid Build Coastguard Worker 
417*f6dc9357SAndroid Build Coastguard Worker const char *GetFileSystem(ISequentialInStream *stream, UInt64 partitionSize)
418*f6dc9357SAndroid Build Coastguard Worker {
419*f6dc9357SAndroid Build Coastguard Worker   const size_t kHeaderSize = 1 << 9;
420*f6dc9357SAndroid Build Coastguard Worker   if (partitionSize >= kHeaderSize)
421*f6dc9357SAndroid Build Coastguard Worker   {
422*f6dc9357SAndroid Build Coastguard Worker     Byte buf[kHeaderSize];
423*f6dc9357SAndroid Build Coastguard Worker     if (ReadStream_FAIL(stream, buf, kHeaderSize) == S_OK)
424*f6dc9357SAndroid Build Coastguard Worker     {
425*f6dc9357SAndroid Build Coastguard Worker       // NTFS is expected default filesystem for (Type == 7)
426*f6dc9357SAndroid Build Coastguard Worker       if (Is_Ntfs(buf))
427*f6dc9357SAndroid Build Coastguard Worker         return "NTFS";
428*f6dc9357SAndroid Build Coastguard Worker       if (Is_ExFat(buf))
429*f6dc9357SAndroid Build Coastguard Worker         return "exFAT";
430*f6dc9357SAndroid Build Coastguard Worker       if (NFat::IsArc_Fat(buf, kHeaderSize))
431*f6dc9357SAndroid Build Coastguard Worker         return "FAT";
432*f6dc9357SAndroid Build Coastguard Worker       const size_t kHeaderSize2 = k_Udf_StartPos + (1 << 9);
433*f6dc9357SAndroid Build Coastguard Worker       if (partitionSize >= kHeaderSize2)
434*f6dc9357SAndroid Build Coastguard Worker       {
435*f6dc9357SAndroid Build Coastguard Worker         if (AllAreZeros(buf, kHeaderSize))
436*f6dc9357SAndroid Build Coastguard Worker         {
437*f6dc9357SAndroid Build Coastguard Worker           CByteBuffer buffer(kHeaderSize2);
438*f6dc9357SAndroid Build Coastguard Worker           // memcpy(buffer, buf, kHeaderSize);
439*f6dc9357SAndroid Build Coastguard Worker           if (ReadStream_FAIL(stream, buffer + kHeaderSize, kHeaderSize2 - kHeaderSize) == S_OK)
440*f6dc9357SAndroid Build Coastguard Worker             if (Is_Udf(buffer))
441*f6dc9357SAndroid Build Coastguard Worker               return "UDF";
442*f6dc9357SAndroid Build Coastguard Worker         }
443*f6dc9357SAndroid Build Coastguard Worker       }
444*f6dc9357SAndroid Build Coastguard Worker     }
445*f6dc9357SAndroid Build Coastguard Worker   }
446*f6dc9357SAndroid Build Coastguard Worker   return NULL;
447*f6dc9357SAndroid Build Coastguard Worker }
448*f6dc9357SAndroid Build Coastguard Worker 
449*f6dc9357SAndroid Build Coastguard Worker 
450*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Open(IInStream *stream,
451*f6dc9357SAndroid Build Coastguard Worker     const UInt64 * /* maxCheckStartPosition */,
452*f6dc9357SAndroid Build Coastguard Worker     IArchiveOpenCallback * /* openArchiveCallback */))
453*f6dc9357SAndroid Build Coastguard Worker {
454*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_BEGIN
455*f6dc9357SAndroid Build Coastguard Worker   Close();
456*f6dc9357SAndroid Build Coastguard Worker   RINOK(InStream_GetSize_SeekToEnd(stream, _totalSize))
457*f6dc9357SAndroid Build Coastguard Worker   RINOK(ReadTables(stream, 0, 0, 0))
458*f6dc9357SAndroid Build Coastguard Worker   if (_items.IsEmpty())
459*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
460*f6dc9357SAndroid Build Coastguard Worker   {
461*f6dc9357SAndroid Build Coastguard Worker     const UInt32 lbaLimit = _items.Back().Part.GetLimit();
462*f6dc9357SAndroid Build Coastguard Worker     const UInt64 lim = (UInt64)lbaLimit << _sectorSizeLog;
463*f6dc9357SAndroid Build Coastguard Worker     if (lim < _totalSize)
464*f6dc9357SAndroid Build Coastguard Worker     {
465*f6dc9357SAndroid Build Coastguard Worker       CItem n;
466*f6dc9357SAndroid Build Coastguard Worker       n.Part.Lba = lbaLimit;
467*f6dc9357SAndroid Build Coastguard Worker       n.Size = _totalSize - lim;
468*f6dc9357SAndroid Build Coastguard Worker       n.IsReal = false;
469*f6dc9357SAndroid Build Coastguard Worker       _items.Add(n);
470*f6dc9357SAndroid Build Coastguard Worker     }
471*f6dc9357SAndroid Build Coastguard Worker   }
472*f6dc9357SAndroid Build Coastguard Worker 
473*f6dc9357SAndroid Build Coastguard Worker   FOR_VECTOR (i, _items)
474*f6dc9357SAndroid Build Coastguard Worker   {
475*f6dc9357SAndroid Build Coastguard Worker     CItem &item = _items[i];
476*f6dc9357SAndroid Build Coastguard Worker     if (item.Part.Type != kType_Windows_NTFS)
477*f6dc9357SAndroid Build Coastguard Worker       continue;
478*f6dc9357SAndroid Build Coastguard Worker     if (InStream_SeekSet(stream, item.Part.GetPos(_sectorSizeLog)) != S_OK)
479*f6dc9357SAndroid Build Coastguard Worker       continue;
480*f6dc9357SAndroid Build Coastguard Worker     item.FileSystem = GetFileSystem(stream, item.Size);
481*f6dc9357SAndroid Build Coastguard Worker     item.WasParsed = true;
482*f6dc9357SAndroid Build Coastguard Worker   }
483*f6dc9357SAndroid Build Coastguard Worker 
484*f6dc9357SAndroid Build Coastguard Worker   _stream = stream;
485*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
486*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_END
487*f6dc9357SAndroid Build Coastguard Worker }
488*f6dc9357SAndroid Build Coastguard Worker 
489*f6dc9357SAndroid Build Coastguard Worker 
490*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Close())
491*f6dc9357SAndroid Build Coastguard Worker {
492*f6dc9357SAndroid Build Coastguard Worker   _totalSize = 0;
493*f6dc9357SAndroid Build Coastguard Worker   _items.Clear();
494*f6dc9357SAndroid Build Coastguard Worker   _stream.Release();
495*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
496*f6dc9357SAndroid Build Coastguard Worker }
497*f6dc9357SAndroid Build Coastguard Worker 
498*f6dc9357SAndroid Build Coastguard Worker 
499*f6dc9357SAndroid Build Coastguard Worker enum
500*f6dc9357SAndroid Build Coastguard Worker {
501*f6dc9357SAndroid Build Coastguard Worker   kpidPrimary = kpidUserDefined,
502*f6dc9357SAndroid Build Coastguard Worker   kpidBegChs,
503*f6dc9357SAndroid Build Coastguard Worker   kpidEndChs
504*f6dc9357SAndroid Build Coastguard Worker };
505*f6dc9357SAndroid Build Coastguard Worker 
506*f6dc9357SAndroid Build Coastguard Worker static const CStatProp kProps[] =
507*f6dc9357SAndroid Build Coastguard Worker {
508*f6dc9357SAndroid Build Coastguard Worker   { NULL, kpidPath, VT_BSTR},
509*f6dc9357SAndroid Build Coastguard Worker   { NULL, kpidSize, VT_UI8},
510*f6dc9357SAndroid Build Coastguard Worker   { NULL, kpidFileSystem, VT_BSTR},
511*f6dc9357SAndroid Build Coastguard Worker   { NULL, kpidOffset, VT_UI8},
512*f6dc9357SAndroid Build Coastguard Worker   { "Primary", kpidPrimary, VT_BOOL},
513*f6dc9357SAndroid Build Coastguard Worker   { "Begin CHS", kpidBegChs, VT_BSTR},
514*f6dc9357SAndroid Build Coastguard Worker   { "End CHS", kpidEndChs, VT_BSTR}
515*f6dc9357SAndroid Build Coastguard Worker };
516*f6dc9357SAndroid Build Coastguard Worker 
517*f6dc9357SAndroid Build Coastguard Worker static const Byte kArcProps[] =
518*f6dc9357SAndroid Build Coastguard Worker {
519*f6dc9357SAndroid Build Coastguard Worker   kpidSectorSize,
520*f6dc9357SAndroid Build Coastguard Worker   kpidId
521*f6dc9357SAndroid Build Coastguard Worker };
522*f6dc9357SAndroid Build Coastguard Worker 
523*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_Props_WITH_NAME
524*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_ArcProps
525*f6dc9357SAndroid Build Coastguard Worker 
526*f6dc9357SAndroid Build Coastguard Worker 
527*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
528*f6dc9357SAndroid Build Coastguard Worker {
529*f6dc9357SAndroid Build Coastguard Worker   NCOM::CPropVariant prop;
530*f6dc9357SAndroid Build Coastguard Worker   switch (propID)
531*f6dc9357SAndroid Build Coastguard Worker   {
532*f6dc9357SAndroid Build Coastguard Worker     case kpidMainSubfile:
533*f6dc9357SAndroid Build Coastguard Worker     {
534*f6dc9357SAndroid Build Coastguard Worker       int mainIndex = -1;
535*f6dc9357SAndroid Build Coastguard Worker       FOR_VECTOR (i, _items)
536*f6dc9357SAndroid Build Coastguard Worker         if (_items[i].IsReal)
537*f6dc9357SAndroid Build Coastguard Worker         {
538*f6dc9357SAndroid Build Coastguard Worker           if (mainIndex >= 0)
539*f6dc9357SAndroid Build Coastguard Worker           {
540*f6dc9357SAndroid Build Coastguard Worker             mainIndex = -1;
541*f6dc9357SAndroid Build Coastguard Worker             break;
542*f6dc9357SAndroid Build Coastguard Worker           }
543*f6dc9357SAndroid Build Coastguard Worker           mainIndex = (int)i;
544*f6dc9357SAndroid Build Coastguard Worker         }
545*f6dc9357SAndroid Build Coastguard Worker       if (mainIndex >= 0)
546*f6dc9357SAndroid Build Coastguard Worker         prop = (UInt32)(Int32)mainIndex;
547*f6dc9357SAndroid Build Coastguard Worker       break;
548*f6dc9357SAndroid Build Coastguard Worker     }
549*f6dc9357SAndroid Build Coastguard Worker     case kpidPhySize: prop = _totalSize; break;
550*f6dc9357SAndroid Build Coastguard Worker     case kpidSectorSize: prop = (UInt32)((UInt32)1 << _sectorSizeLog); break;
551*f6dc9357SAndroid Build Coastguard Worker     case kpidId: prop = _signature; break;
552*f6dc9357SAndroid Build Coastguard Worker   }
553*f6dc9357SAndroid Build Coastguard Worker   prop.Detach(value);
554*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
555*f6dc9357SAndroid Build Coastguard Worker }
556*f6dc9357SAndroid Build Coastguard Worker 
557*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
558*f6dc9357SAndroid Build Coastguard Worker {
559*f6dc9357SAndroid Build Coastguard Worker   *numItems = _items.Size();
560*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
561*f6dc9357SAndroid Build Coastguard Worker }
562*f6dc9357SAndroid Build Coastguard Worker 
563*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))
564*f6dc9357SAndroid Build Coastguard Worker {
565*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_BEGIN
566*f6dc9357SAndroid Build Coastguard Worker   NCOM::CPropVariant prop;
567*f6dc9357SAndroid Build Coastguard Worker 
568*f6dc9357SAndroid Build Coastguard Worker   const CItem &item = _items[index];
569*f6dc9357SAndroid Build Coastguard Worker   const CPartition &part = item.Part;
570*f6dc9357SAndroid Build Coastguard Worker   switch (propID)
571*f6dc9357SAndroid Build Coastguard Worker   {
572*f6dc9357SAndroid Build Coastguard Worker     case kpidPath:
573*f6dc9357SAndroid Build Coastguard Worker     {
574*f6dc9357SAndroid Build Coastguard Worker       AString s;
575*f6dc9357SAndroid Build Coastguard Worker       s.Add_UInt32(index);
576*f6dc9357SAndroid Build Coastguard Worker       if (item.IsReal)
577*f6dc9357SAndroid Build Coastguard Worker       {
578*f6dc9357SAndroid Build Coastguard Worker         s.Add_Dot();
579*f6dc9357SAndroid Build Coastguard Worker         const char *ext = NULL;
580*f6dc9357SAndroid Build Coastguard Worker         if (item.FileSystem)
581*f6dc9357SAndroid Build Coastguard Worker         {
582*f6dc9357SAndroid Build Coastguard Worker           ext = "";
583*f6dc9357SAndroid Build Coastguard Worker           AString fs (item.FileSystem);
584*f6dc9357SAndroid Build Coastguard Worker           fs.MakeLower_Ascii();
585*f6dc9357SAndroid Build Coastguard Worker           s += fs;
586*f6dc9357SAndroid Build Coastguard Worker         }
587*f6dc9357SAndroid Build Coastguard Worker         else if (!item.WasParsed)
588*f6dc9357SAndroid Build Coastguard Worker         {
589*f6dc9357SAndroid Build Coastguard Worker           const int typeIndex = FindPartType(part.Type);
590*f6dc9357SAndroid Build Coastguard Worker           if (typeIndex >= 0)
591*f6dc9357SAndroid Build Coastguard Worker             ext = kPartTypes[(unsigned)typeIndex].Ext;
592*f6dc9357SAndroid Build Coastguard Worker         }
593*f6dc9357SAndroid Build Coastguard Worker         if (!ext)
594*f6dc9357SAndroid Build Coastguard Worker           ext = "img";
595*f6dc9357SAndroid Build Coastguard Worker         s += ext;
596*f6dc9357SAndroid Build Coastguard Worker       }
597*f6dc9357SAndroid Build Coastguard Worker       prop = s;
598*f6dc9357SAndroid Build Coastguard Worker       break;
599*f6dc9357SAndroid Build Coastguard Worker     }
600*f6dc9357SAndroid Build Coastguard Worker     case kpidFileSystem:
601*f6dc9357SAndroid Build Coastguard Worker       if (item.IsReal)
602*f6dc9357SAndroid Build Coastguard Worker       {
603*f6dc9357SAndroid Build Coastguard Worker         char s[32];
604*f6dc9357SAndroid Build Coastguard Worker         ConvertUInt32ToString(part.Type, s);
605*f6dc9357SAndroid Build Coastguard Worker         const char *res = s;
606*f6dc9357SAndroid Build Coastguard Worker         if (item.FileSystem)
607*f6dc9357SAndroid Build Coastguard Worker         {
608*f6dc9357SAndroid Build Coastguard Worker           // strcat(s, "-");
609*f6dc9357SAndroid Build Coastguard Worker           // strcpy(s, item.FileSystem);
610*f6dc9357SAndroid Build Coastguard Worker           res = item.FileSystem;
611*f6dc9357SAndroid Build Coastguard Worker         }
612*f6dc9357SAndroid Build Coastguard Worker         else if (!item.WasParsed)
613*f6dc9357SAndroid Build Coastguard Worker         {
614*f6dc9357SAndroid Build Coastguard Worker           const int typeIndex = FindPartType(part.Type);
615*f6dc9357SAndroid Build Coastguard Worker           if (typeIndex >= 0 && kPartTypes[(unsigned)typeIndex].Name)
616*f6dc9357SAndroid Build Coastguard Worker             res = kPartTypes[(unsigned)typeIndex].Name;
617*f6dc9357SAndroid Build Coastguard Worker         }
618*f6dc9357SAndroid Build Coastguard Worker         prop = res;
619*f6dc9357SAndroid Build Coastguard Worker       }
620*f6dc9357SAndroid Build Coastguard Worker       break;
621*f6dc9357SAndroid Build Coastguard Worker     case kpidSize:
622*f6dc9357SAndroid Build Coastguard Worker     case kpidPackSize: prop = item.Size; break;
623*f6dc9357SAndroid Build Coastguard Worker     case kpidOffset: prop = part.GetPos(_sectorSizeLog); break;
624*f6dc9357SAndroid Build Coastguard Worker     case kpidPrimary: if (item.IsReal) prop = item.IsPrim; break;
625*f6dc9357SAndroid Build Coastguard Worker     case kpidBegChs: if (item.IsReal) part.BeginChs.ToString(prop); break;
626*f6dc9357SAndroid Build Coastguard Worker     case kpidEndChs: if (item.IsReal) part.EndChs.ToString(prop); break;
627*f6dc9357SAndroid Build Coastguard Worker   }
628*f6dc9357SAndroid Build Coastguard Worker   prop.Detach(value);
629*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
630*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_END
631*f6dc9357SAndroid Build Coastguard Worker }
632*f6dc9357SAndroid Build Coastguard Worker 
633*f6dc9357SAndroid Build Coastguard Worker 
634*f6dc9357SAndroid Build Coastguard Worker   // 3, { 1, 1, 0 },
635*f6dc9357SAndroid Build Coastguard Worker   // 2, { 0x55, 0x1FF },
636*f6dc9357SAndroid Build Coastguard Worker 
637*f6dc9357SAndroid Build Coastguard Worker REGISTER_ARC_I_NO_SIG(
638*f6dc9357SAndroid Build Coastguard Worker   "MBR", "mbr", NULL, 0xDB,
639*f6dc9357SAndroid Build Coastguard Worker   0,
640*f6dc9357SAndroid Build Coastguard Worker   NArcInfoFlags::kPureStartOpen,
641*f6dc9357SAndroid Build Coastguard Worker   NULL)
642*f6dc9357SAndroid Build Coastguard Worker 
643*f6dc9357SAndroid Build Coastguard Worker }}
644