xref: /aosp_15_r20/external/lzma/CPP/7zip/Archive/ApmHandler.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker // ApmHandler.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 
9*f6dc9357SAndroid Build Coastguard Worker #include "../../Windows/PropVariantUtils.h"
10*f6dc9357SAndroid Build Coastguard Worker 
11*f6dc9357SAndroid Build Coastguard Worker #include "../Common/RegisterArc.h"
12*f6dc9357SAndroid Build Coastguard Worker #include "../Common/StreamUtils.h"
13*f6dc9357SAndroid Build Coastguard Worker 
14*f6dc9357SAndroid Build Coastguard Worker #include "HandlerCont.h"
15*f6dc9357SAndroid Build Coastguard Worker 
16*f6dc9357SAndroid Build Coastguard Worker #define Get32(p) GetBe32a(p)
17*f6dc9357SAndroid Build Coastguard Worker 
18*f6dc9357SAndroid Build Coastguard Worker using namespace NWindows;
19*f6dc9357SAndroid Build Coastguard Worker 
20*f6dc9357SAndroid Build Coastguard Worker namespace NArchive {
21*f6dc9357SAndroid Build Coastguard Worker 
22*f6dc9357SAndroid Build Coastguard Worker namespace NDmg {
23*f6dc9357SAndroid Build Coastguard Worker   const char *Find_Apple_FS_Ext(const AString &name);
24*f6dc9357SAndroid Build Coastguard Worker   bool Is_Apple_FS_Or_Unknown(const AString &name);
25*f6dc9357SAndroid Build Coastguard Worker }
26*f6dc9357SAndroid Build Coastguard Worker 
27*f6dc9357SAndroid Build Coastguard Worker namespace NApm {
28*f6dc9357SAndroid Build Coastguard Worker 
29*f6dc9357SAndroid Build Coastguard Worker static const Byte kSig0 = 'E';
30*f6dc9357SAndroid Build Coastguard Worker static const Byte kSig1 = 'R';
31*f6dc9357SAndroid Build Coastguard Worker 
32*f6dc9357SAndroid Build Coastguard Worker static const CUInt32PCharPair k_Flags[] =
33*f6dc9357SAndroid Build Coastguard Worker {
34*f6dc9357SAndroid Build Coastguard Worker   { 0, "VALID" },
35*f6dc9357SAndroid Build Coastguard Worker   { 1, "ALLOCATED" },
36*f6dc9357SAndroid Build Coastguard Worker   { 2, "IN_USE" },
37*f6dc9357SAndroid Build Coastguard Worker   { 3, "BOOTABLE" },
38*f6dc9357SAndroid Build Coastguard Worker   { 4, "READABLE" },
39*f6dc9357SAndroid Build Coastguard Worker   { 5, "WRITABLE" },
40*f6dc9357SAndroid Build Coastguard Worker   { 6, "OS_PIC_CODE" },
41*f6dc9357SAndroid Build Coastguard Worker   // { 7, "OS_SPECIFIC_2" }, // "Unused"
42*f6dc9357SAndroid Build Coastguard Worker   { 8, "ChainCompatible" }, // "OS_SPECIFIC_1"
43*f6dc9357SAndroid Build Coastguard Worker   { 9, "RealDeviceDriver" },
44*f6dc9357SAndroid Build Coastguard Worker   // { 10, "CanChainToNext" },
45*f6dc9357SAndroid Build Coastguard Worker   { 30, "MOUNTED_AT_STARTUP" },
46*f6dc9357SAndroid Build Coastguard Worker   { 31, "STARTUP" }
47*f6dc9357SAndroid Build Coastguard Worker };
48*f6dc9357SAndroid Build Coastguard Worker 
49*f6dc9357SAndroid Build Coastguard Worker #define DPME_FLAGS_VALID      (1u << 0)
50*f6dc9357SAndroid Build Coastguard Worker #define DPME_FLAGS_ALLOCATED  (1u << 1)
51*f6dc9357SAndroid Build Coastguard Worker 
52*f6dc9357SAndroid Build Coastguard Worker static const unsigned k_Str_Size = 32;
53*f6dc9357SAndroid Build Coastguard Worker 
54*f6dc9357SAndroid Build Coastguard Worker struct CItem
55*f6dc9357SAndroid Build Coastguard Worker {
56*f6dc9357SAndroid Build Coastguard Worker   UInt32 StartBlock;
57*f6dc9357SAndroid Build Coastguard Worker   UInt32 NumBlocks;
58*f6dc9357SAndroid Build Coastguard Worker   UInt32 Flags; // pmPartStatus
59*f6dc9357SAndroid Build Coastguard Worker   char Name[k_Str_Size];
60*f6dc9357SAndroid Build Coastguard Worker   char Type[k_Str_Size];
61*f6dc9357SAndroid Build Coastguard Worker   /*
62*f6dc9357SAndroid Build Coastguard Worker   UInt32 DataStartBlock;
63*f6dc9357SAndroid Build Coastguard Worker   UInt32 NumDataBlocks;
64*f6dc9357SAndroid Build Coastguard Worker   UInt32 BootStartBlock;
65*f6dc9357SAndroid Build Coastguard Worker   UInt32 BootSize;
66*f6dc9357SAndroid Build Coastguard Worker   UInt32 BootAddr;
67*f6dc9357SAndroid Build Coastguard Worker   UInt32 BootEntry;
68*f6dc9357SAndroid Build Coastguard Worker   UInt32 BootChecksum;
69*f6dc9357SAndroid Build Coastguard Worker   char Processor[16];
70*f6dc9357SAndroid Build Coastguard Worker   */
71*f6dc9357SAndroid Build Coastguard Worker 
Is_Valid_and_AllocatedNArchive::NApm::CItem72*f6dc9357SAndroid Build Coastguard Worker   bool Is_Valid_and_Allocated() const
73*f6dc9357SAndroid Build Coastguard Worker     { return (Flags & (DPME_FLAGS_VALID | DPME_FLAGS_ALLOCATED)) != 0; }
74*f6dc9357SAndroid Build Coastguard Worker 
ParseNArchive::NApm::CItem75*f6dc9357SAndroid Build Coastguard Worker   bool Parse(const UInt32 *p32, UInt32 &numBlocksInMap)
76*f6dc9357SAndroid Build Coastguard Worker   {
77*f6dc9357SAndroid Build Coastguard Worker     if (GetUi32a(p32) != 0x4d50) // "PM"
78*f6dc9357SAndroid Build Coastguard Worker       return false;
79*f6dc9357SAndroid Build Coastguard Worker     numBlocksInMap = Get32(p32 + 4 / 4);
80*f6dc9357SAndroid Build Coastguard Worker     StartBlock = Get32(p32 + 8 / 4);
81*f6dc9357SAndroid Build Coastguard Worker     NumBlocks = Get32(p32 + 0xc / 4);
82*f6dc9357SAndroid Build Coastguard Worker     Flags = Get32(p32 + 0x58 / 4);
83*f6dc9357SAndroid Build Coastguard Worker     memcpy(Name, p32 + 0x10 / 4, k_Str_Size);
84*f6dc9357SAndroid Build Coastguard Worker     memcpy(Type, p32 + 0x30 / 4, k_Str_Size);
85*f6dc9357SAndroid Build Coastguard Worker     /*
86*f6dc9357SAndroid Build Coastguard Worker     DataStartBlock = Get32(p + 0x50);
87*f6dc9357SAndroid Build Coastguard Worker     NumDataBlocks = Get32(p + 0x54);
88*f6dc9357SAndroid Build Coastguard Worker     BootStartBlock = Get32(p + 0x5c);
89*f6dc9357SAndroid Build Coastguard Worker     BootSize = Get32(p + 0x60);
90*f6dc9357SAndroid Build Coastguard Worker     BootAddr = Get32(p + 0x64);
91*f6dc9357SAndroid Build Coastguard Worker     if (Get32(p + 0x68) != 0)
92*f6dc9357SAndroid Build Coastguard Worker       return false;
93*f6dc9357SAndroid Build Coastguard Worker     BootEntry = Get32(p + 0x6c);
94*f6dc9357SAndroid Build Coastguard Worker     if (Get32(p + 0x70) != 0)
95*f6dc9357SAndroid Build Coastguard Worker       return false;
96*f6dc9357SAndroid Build Coastguard Worker     BootChecksum = Get32(p + 0x74);
97*f6dc9357SAndroid Build Coastguard Worker     memcpy(Processor, p32 + 0x78 / 4, 16);
98*f6dc9357SAndroid Build Coastguard Worker     */
99*f6dc9357SAndroid Build Coastguard Worker     return true;
100*f6dc9357SAndroid Build Coastguard Worker   }
101*f6dc9357SAndroid Build Coastguard Worker };
102*f6dc9357SAndroid Build Coastguard Worker 
103*f6dc9357SAndroid Build Coastguard Worker 
104*f6dc9357SAndroid Build Coastguard Worker Z7_class_CHandler_final: public CHandlerCont
105*f6dc9357SAndroid Build Coastguard Worker {
106*f6dc9357SAndroid Build Coastguard Worker   Z7_IFACE_COM7_IMP(IInArchive_Cont)
107*f6dc9357SAndroid Build Coastguard Worker 
108*f6dc9357SAndroid Build Coastguard Worker   CRecordVector<CItem> _items;
109*f6dc9357SAndroid Build Coastguard Worker   unsigned _blockSizeLog;
110*f6dc9357SAndroid Build Coastguard Worker   bool _isArc;
111*f6dc9357SAndroid Build Coastguard Worker   // UInt32 _numBlocks;
112*f6dc9357SAndroid Build Coastguard Worker   UInt64 _phySize;
113*f6dc9357SAndroid Build Coastguard Worker 
114*f6dc9357SAndroid Build Coastguard Worker   UInt64 BlocksToBytes(UInt32 i) const { return (UInt64)i << _blockSizeLog; }
115*f6dc9357SAndroid Build Coastguard Worker 
116*f6dc9357SAndroid Build Coastguard Worker   virtual int GetItem_ExtractInfo(UInt32 index, UInt64 &pos, UInt64 &size) const Z7_override
117*f6dc9357SAndroid Build Coastguard Worker   {
118*f6dc9357SAndroid Build Coastguard Worker     const CItem &item = _items[index];
119*f6dc9357SAndroid Build Coastguard Worker     pos = BlocksToBytes(item.StartBlock);
120*f6dc9357SAndroid Build Coastguard Worker     size = BlocksToBytes(item.NumBlocks);
121*f6dc9357SAndroid Build Coastguard Worker     return NExtract::NOperationResult::kOK;
122*f6dc9357SAndroid Build Coastguard Worker   }
123*f6dc9357SAndroid Build Coastguard Worker };
124*f6dc9357SAndroid Build Coastguard Worker 
125*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kSectorSize = 512;
126*f6dc9357SAndroid Build Coastguard Worker 
127*f6dc9357SAndroid Build Coastguard Worker // we support only 4 cluster sizes: 512, 1024, 2048, 4096 */
128*f6dc9357SAndroid Build Coastguard Worker 
129*f6dc9357SAndroid Build Coastguard Worker API_FUNC_static_IsArc IsArc_Apm(const Byte *p, size_t size)
130*f6dc9357SAndroid Build Coastguard Worker {
131*f6dc9357SAndroid Build Coastguard Worker   if (size < kSectorSize)
132*f6dc9357SAndroid Build Coastguard Worker     return k_IsArc_Res_NEED_MORE;
133*f6dc9357SAndroid Build Coastguard Worker   if (GetUi32(p + 12) != 0)
134*f6dc9357SAndroid Build Coastguard Worker     return k_IsArc_Res_NO;
135*f6dc9357SAndroid Build Coastguard Worker   UInt32 v = GetUi32(p); // we read as little-endian
136*f6dc9357SAndroid Build Coastguard Worker   v ^= kSig0 | (unsigned)kSig1 << 8;
137*f6dc9357SAndroid Build Coastguard Worker   if (v & ~((UInt32)0xf << 17))
138*f6dc9357SAndroid Build Coastguard Worker     return k_IsArc_Res_NO;
139*f6dc9357SAndroid Build Coastguard Worker   if ((0x116u >> (v >> 17)) & 1)
140*f6dc9357SAndroid Build Coastguard Worker     return k_IsArc_Res_YES;
141*f6dc9357SAndroid Build Coastguard Worker   return k_IsArc_Res_NO;
142*f6dc9357SAndroid Build Coastguard Worker }
143*f6dc9357SAndroid Build Coastguard Worker }
144*f6dc9357SAndroid Build Coastguard Worker 
145*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback * /* callback */))
146*f6dc9357SAndroid Build Coastguard Worker {
147*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_BEGIN
148*f6dc9357SAndroid Build Coastguard Worker   Close();
149*f6dc9357SAndroid Build Coastguard Worker 
150*f6dc9357SAndroid Build Coastguard Worker   UInt32 buf32[kSectorSize / 4];
151*f6dc9357SAndroid Build Coastguard Worker   unsigned numPadSectors, blockSizeLog_from_Header;
152*f6dc9357SAndroid Build Coastguard Worker   {
153*f6dc9357SAndroid Build Coastguard Worker     // Driver Descriptor Map (DDM)
154*f6dc9357SAndroid Build Coastguard Worker     RINOK(ReadStream_FALSE(stream, buf32, kSectorSize))
155*f6dc9357SAndroid Build Coastguard Worker     //  8: UInt16 sbDevType : =0 (usually), =1 in Apple Mac OS X 10.3.0 iso
156*f6dc9357SAndroid Build Coastguard Worker     // 10: UInt16 sbDevId   : =0 (usually), =1 in Apple Mac OS X 10.3.0 iso
157*f6dc9357SAndroid Build Coastguard Worker     // 12: UInt32 sbData    : =0
158*f6dc9357SAndroid Build Coastguard Worker     if (buf32[3] != 0)
159*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
160*f6dc9357SAndroid Build Coastguard Worker     UInt32 v = GetUi32a(buf32); // we read as little-endian
161*f6dc9357SAndroid Build Coastguard Worker     v ^= kSig0 | (unsigned)kSig1 << 8;
162*f6dc9357SAndroid Build Coastguard Worker     if (v & ~((UInt32)0xf << 17))
163*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
164*f6dc9357SAndroid Build Coastguard Worker     v >>= 16;
165*f6dc9357SAndroid Build Coastguard Worker     if (v == 0)
166*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
167*f6dc9357SAndroid Build Coastguard Worker     if (v & (v - 1))
168*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
169*f6dc9357SAndroid Build Coastguard Worker     // v == { 16,8,4,2 } : block size (x256 bytes)
170*f6dc9357SAndroid Build Coastguard Worker     const unsigned a =
171*f6dc9357SAndroid Build Coastguard Worker #if 1
172*f6dc9357SAndroid Build Coastguard Worker         (0x30210u >> v) & 3;
173*f6dc9357SAndroid Build Coastguard Worker #else
174*f6dc9357SAndroid Build Coastguard Worker         0; // for debug : hardcoded switch to 512-bytes mode
175*f6dc9357SAndroid Build Coastguard Worker #endif
176*f6dc9357SAndroid Build Coastguard Worker     numPadSectors = (1u << a) - 1;
177*f6dc9357SAndroid Build Coastguard Worker     _blockSizeLog = blockSizeLog_from_Header = 9 + a;
178*f6dc9357SAndroid Build Coastguard Worker   }
179*f6dc9357SAndroid Build Coastguard Worker 
180*f6dc9357SAndroid Build Coastguard Worker /*
181*f6dc9357SAndroid Build Coastguard Worker   some APMs (that are ".iso" macOS installation files) contain
182*f6dc9357SAndroid Build Coastguard Worker     (blockSizeLog == 11) in DDM header,
183*f6dc9357SAndroid Build Coastguard Worker   and contain 2 overlapping maps:
184*f6dc9357SAndroid Build Coastguard Worker     1) map for  512-bytes-step
185*f6dc9357SAndroid Build Coastguard Worker     2) map for 2048-bytes-step
186*f6dc9357SAndroid Build Coastguard Worker    512-bytes-step map is correct.
187*f6dc9357SAndroid Build Coastguard Worker   2048-bytes-step map can be incorrect in some cases.
188*f6dc9357SAndroid Build Coastguard Worker 
189*f6dc9357SAndroid Build Coastguard Worker   macos 8 / OSX DP2 iso:
190*f6dc9357SAndroid Build Coastguard Worker     There is shared "hfs" item in both maps.
191*f6dc9357SAndroid Build Coastguard Worker     And correct (offset/size) values for "hfs" partition
192*f6dc9357SAndroid Build Coastguard Worker     can be calculated only in 512-bytes mode (ignoring blockSizeLog == 11).
193*f6dc9357SAndroid Build Coastguard Worker     But some records (Macintosh.Apple_Driver*_)
194*f6dc9357SAndroid Build Coastguard Worker     can be correct on both modes: 512-bytes mode / 2048-bytes-step.
195*f6dc9357SAndroid Build Coastguard Worker 
196*f6dc9357SAndroid Build Coastguard Worker   macos 921 ppc / Apple Mac OS X 10.3.0 iso:
197*f6dc9357SAndroid Build Coastguard Worker     Both maps are correct.
198*f6dc9357SAndroid Build Coastguard Worker     If we use 512-bytes-step, each 4th item is (Apple_Void) with zero size.
199*f6dc9357SAndroid Build Coastguard Worker     And these zero size (Apple_Void) items will be first items in 2048-bytes-step map.
200*f6dc9357SAndroid Build Coastguard Worker */
201*f6dc9357SAndroid Build Coastguard Worker 
202*f6dc9357SAndroid Build Coastguard Worker // we define Z7_APM_SWITCH_TO_512_BYTES, because
203*f6dc9357SAndroid Build Coastguard Worker // we want to support old MACOS APMs that contain correct value only
204*f6dc9357SAndroid Build Coastguard Worker // for 512-bytes-step mode
205*f6dc9357SAndroid Build Coastguard Worker #define Z7_APM_SWITCH_TO_512_BYTES
206*f6dc9357SAndroid Build Coastguard Worker 
207*f6dc9357SAndroid Build Coastguard Worker   const UInt32 numBlocks_from_Header = Get32(buf32 + 1);
208*f6dc9357SAndroid Build Coastguard Worker   UInt32 numBlocks = 0;
209*f6dc9357SAndroid Build Coastguard Worker   {
210*f6dc9357SAndroid Build Coastguard Worker     for (unsigned k = 0; k < numPadSectors; k++)
211*f6dc9357SAndroid Build Coastguard Worker     {
212*f6dc9357SAndroid Build Coastguard Worker       RINOK(ReadStream_FALSE(stream, buf32, kSectorSize))
213*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_APM_SWITCH_TO_512_BYTES
214*f6dc9357SAndroid Build Coastguard Worker       if (k == 0)
215*f6dc9357SAndroid Build Coastguard Worker       {
216*f6dc9357SAndroid Build Coastguard Worker         if (GetUi32a(buf32) == 0x4d50        // "PM"
217*f6dc9357SAndroid Build Coastguard Worker             // && (Get32(buf32 + 0x58 / 4) & 1) // Flags::VALID
218*f6dc9357SAndroid Build Coastguard Worker             // some old APMs don't use VALID flag for Apple_partition_map item
219*f6dc9357SAndroid Build Coastguard Worker             && Get32(buf32 + 8 / 4) == 1)    // StartBlock
220*f6dc9357SAndroid Build Coastguard Worker         {
221*f6dc9357SAndroid Build Coastguard Worker           // we switch the mode to 512-bytes-step map reading:
222*f6dc9357SAndroid Build Coastguard Worker           numPadSectors = 0;
223*f6dc9357SAndroid Build Coastguard Worker           _blockSizeLog = 9;
224*f6dc9357SAndroid Build Coastguard Worker           break;
225*f6dc9357SAndroid Build Coastguard Worker         }
226*f6dc9357SAndroid Build Coastguard Worker       }
227*f6dc9357SAndroid Build Coastguard Worker #endif
228*f6dc9357SAndroid Build Coastguard Worker     }
229*f6dc9357SAndroid Build Coastguard Worker   }
230*f6dc9357SAndroid Build Coastguard Worker 
231*f6dc9357SAndroid Build Coastguard Worker   for (unsigned i = 0;;)
232*f6dc9357SAndroid Build Coastguard Worker   {
233*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_APM_SWITCH_TO_512_BYTES
234*f6dc9357SAndroid Build Coastguard Worker     if (i != 0 || _blockSizeLog == blockSizeLog_from_Header)
235*f6dc9357SAndroid Build Coastguard Worker #endif
236*f6dc9357SAndroid Build Coastguard Worker     {
237*f6dc9357SAndroid Build Coastguard Worker       RINOK(ReadStream_FALSE(stream, buf32, kSectorSize))
238*f6dc9357SAndroid Build Coastguard Worker     }
239*f6dc9357SAndroid Build Coastguard Worker 
240*f6dc9357SAndroid Build Coastguard Worker     CItem item;
241*f6dc9357SAndroid Build Coastguard Worker     UInt32 numBlocksInMap = 0;
242*f6dc9357SAndroid Build Coastguard Worker     if (!item.Parse(buf32, numBlocksInMap))
243*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
244*f6dc9357SAndroid Build Coastguard Worker     // v24.09: we don't check that all entries have same (numBlocksInMap) values,
245*f6dc9357SAndroid Build Coastguard Worker     // because some APMs have different (numBlocksInMap) values, if (Apple_Void) is used.
246*f6dc9357SAndroid Build Coastguard Worker     if (numBlocksInMap > (1 << 8) || numBlocksInMap <= i)
247*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
248*f6dc9357SAndroid Build Coastguard Worker 
249*f6dc9357SAndroid Build Coastguard Worker     const UInt32 finish = item.StartBlock + item.NumBlocks;
250*f6dc9357SAndroid Build Coastguard Worker     if (finish < item.StartBlock)
251*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
252*f6dc9357SAndroid Build Coastguard Worker     if (numBlocks < finish)
253*f6dc9357SAndroid Build Coastguard Worker         numBlocks = finish;
254*f6dc9357SAndroid Build Coastguard Worker 
255*f6dc9357SAndroid Build Coastguard Worker     _items.Add(item);
256*f6dc9357SAndroid Build Coastguard Worker     if (numPadSectors != 0)
257*f6dc9357SAndroid Build Coastguard Worker     {
258*f6dc9357SAndroid Build Coastguard Worker       RINOK(stream->Seek(numPadSectors << 9, STREAM_SEEK_CUR, NULL))
259*f6dc9357SAndroid Build Coastguard Worker     }
260*f6dc9357SAndroid Build Coastguard Worker     if (++i == numBlocksInMap)
261*f6dc9357SAndroid Build Coastguard Worker       break;
262*f6dc9357SAndroid Build Coastguard Worker   }
263*f6dc9357SAndroid Build Coastguard Worker 
264*f6dc9357SAndroid Build Coastguard Worker   _phySize = BlocksToBytes(numBlocks);
265*f6dc9357SAndroid Build Coastguard Worker   // _numBlocks = numBlocks;
266*f6dc9357SAndroid Build Coastguard Worker   const UInt64 physSize = (UInt64)numBlocks_from_Header << blockSizeLog_from_Header;
267*f6dc9357SAndroid Build Coastguard Worker   if (_phySize < physSize)
268*f6dc9357SAndroid Build Coastguard Worker       _phySize = physSize;
269*f6dc9357SAndroid Build Coastguard Worker   _isArc = true;
270*f6dc9357SAndroid Build Coastguard Worker   _stream = stream;
271*f6dc9357SAndroid Build Coastguard Worker 
272*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
273*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_END
274*f6dc9357SAndroid Build Coastguard Worker }
275*f6dc9357SAndroid Build Coastguard Worker 
276*f6dc9357SAndroid Build Coastguard Worker 
277*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Close())
278*f6dc9357SAndroid Build Coastguard Worker {
279*f6dc9357SAndroid Build Coastguard Worker   _isArc = false;
280*f6dc9357SAndroid Build Coastguard Worker   _phySize = 0;
281*f6dc9357SAndroid Build Coastguard Worker   _items.Clear();
282*f6dc9357SAndroid Build Coastguard Worker   _stream.Release();
283*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
284*f6dc9357SAndroid Build Coastguard Worker }
285*f6dc9357SAndroid Build Coastguard Worker 
286*f6dc9357SAndroid Build Coastguard Worker 
287*f6dc9357SAndroid Build Coastguard Worker static const Byte kProps[] =
288*f6dc9357SAndroid Build Coastguard Worker {
289*f6dc9357SAndroid Build Coastguard Worker   kpidPath,
290*f6dc9357SAndroid Build Coastguard Worker   kpidSize,
291*f6dc9357SAndroid Build Coastguard Worker   kpidOffset,
292*f6dc9357SAndroid Build Coastguard Worker   kpidCharacts
293*f6dc9357SAndroid Build Coastguard Worker   // , kpidCpu
294*f6dc9357SAndroid Build Coastguard Worker };
295*f6dc9357SAndroid Build Coastguard Worker 
296*f6dc9357SAndroid Build Coastguard Worker static const Byte kArcProps[] =
297*f6dc9357SAndroid Build Coastguard Worker {
298*f6dc9357SAndroid Build Coastguard Worker   kpidClusterSize
299*f6dc9357SAndroid Build Coastguard Worker   // , kpidNumBlocks
300*f6dc9357SAndroid Build Coastguard Worker };
301*f6dc9357SAndroid Build Coastguard Worker 
302*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_Props
303*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_ArcProps
304*f6dc9357SAndroid Build Coastguard Worker 
305*f6dc9357SAndroid Build Coastguard Worker static void GetString(AString &dest, const char *src)
306*f6dc9357SAndroid Build Coastguard Worker {
307*f6dc9357SAndroid Build Coastguard Worker   dest.SetFrom_CalcLen(src, k_Str_Size);
308*f6dc9357SAndroid Build Coastguard Worker }
309*f6dc9357SAndroid Build Coastguard Worker 
310*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
311*f6dc9357SAndroid Build Coastguard Worker {
312*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_BEGIN
313*f6dc9357SAndroid Build Coastguard Worker   NCOM::CPropVariant prop;
314*f6dc9357SAndroid Build Coastguard Worker   switch (propID)
315*f6dc9357SAndroid Build Coastguard Worker   {
316*f6dc9357SAndroid Build Coastguard Worker     case kpidMainSubfile:
317*f6dc9357SAndroid Build Coastguard Worker     {
318*f6dc9357SAndroid Build Coastguard Worker       int mainIndex = -1;
319*f6dc9357SAndroid Build Coastguard Worker       FOR_VECTOR (i, _items)
320*f6dc9357SAndroid Build Coastguard Worker       {
321*f6dc9357SAndroid Build Coastguard Worker         const CItem &item = _items[i];
322*f6dc9357SAndroid Build Coastguard Worker         if (!item.Is_Valid_and_Allocated())
323*f6dc9357SAndroid Build Coastguard Worker           continue;
324*f6dc9357SAndroid Build Coastguard Worker         AString s;
325*f6dc9357SAndroid Build Coastguard Worker         GetString(s, item.Type);
326*f6dc9357SAndroid Build Coastguard Worker         if (NDmg::Is_Apple_FS_Or_Unknown(s))
327*f6dc9357SAndroid Build Coastguard Worker         {
328*f6dc9357SAndroid Build Coastguard Worker           if (mainIndex != -1)
329*f6dc9357SAndroid Build Coastguard Worker           {
330*f6dc9357SAndroid Build Coastguard Worker             mainIndex = -1;
331*f6dc9357SAndroid Build Coastguard Worker             break;
332*f6dc9357SAndroid Build Coastguard Worker           }
333*f6dc9357SAndroid Build Coastguard Worker           mainIndex = (int)i;
334*f6dc9357SAndroid Build Coastguard Worker         }
335*f6dc9357SAndroid Build Coastguard Worker       }
336*f6dc9357SAndroid Build Coastguard Worker       if (mainIndex != -1)
337*f6dc9357SAndroid Build Coastguard Worker         prop = (UInt32)(Int32)mainIndex;
338*f6dc9357SAndroid Build Coastguard Worker       break;
339*f6dc9357SAndroid Build Coastguard Worker     }
340*f6dc9357SAndroid Build Coastguard Worker     case kpidClusterSize: prop = (UInt32)1 << _blockSizeLog; break;
341*f6dc9357SAndroid Build Coastguard Worker     case kpidPhySize: prop = _phySize; break;
342*f6dc9357SAndroid Build Coastguard Worker     // case kpidNumBlocks: prop = _numBlocks; break;
343*f6dc9357SAndroid Build Coastguard Worker 
344*f6dc9357SAndroid Build Coastguard Worker     case kpidErrorFlags:
345*f6dc9357SAndroid Build Coastguard Worker     {
346*f6dc9357SAndroid Build Coastguard Worker       UInt32 v = 0;
347*f6dc9357SAndroid Build Coastguard Worker       if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;
348*f6dc9357SAndroid Build Coastguard Worker       prop = v;
349*f6dc9357SAndroid Build Coastguard Worker       break;
350*f6dc9357SAndroid Build Coastguard Worker     }
351*f6dc9357SAndroid Build Coastguard Worker   }
352*f6dc9357SAndroid Build Coastguard Worker   prop.Detach(value);
353*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
354*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_END
355*f6dc9357SAndroid Build Coastguard Worker }
356*f6dc9357SAndroid Build Coastguard Worker 
357*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
358*f6dc9357SAndroid Build Coastguard Worker {
359*f6dc9357SAndroid Build Coastguard Worker   *numItems = _items.Size();
360*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
361*f6dc9357SAndroid Build Coastguard Worker }
362*f6dc9357SAndroid Build Coastguard Worker 
363*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))
364*f6dc9357SAndroid Build Coastguard Worker {
365*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_BEGIN
366*f6dc9357SAndroid Build Coastguard Worker   NCOM::CPropVariant prop;
367*f6dc9357SAndroid Build Coastguard Worker   const CItem &item = _items[index];
368*f6dc9357SAndroid Build Coastguard Worker   switch (propID)
369*f6dc9357SAndroid Build Coastguard Worker   {
370*f6dc9357SAndroid Build Coastguard Worker     case kpidPath:
371*f6dc9357SAndroid Build Coastguard Worker     {
372*f6dc9357SAndroid Build Coastguard Worker       AString s;
373*f6dc9357SAndroid Build Coastguard Worker       GetString(s, item.Name);
374*f6dc9357SAndroid Build Coastguard Worker       if (s.IsEmpty())
375*f6dc9357SAndroid Build Coastguard Worker         s.Add_UInt32(index);
376*f6dc9357SAndroid Build Coastguard Worker       AString type;
377*f6dc9357SAndroid Build Coastguard Worker       GetString(type, item.Type);
378*f6dc9357SAndroid Build Coastguard Worker       {
379*f6dc9357SAndroid Build Coastguard Worker         const char *ext = NDmg::Find_Apple_FS_Ext(type);
380*f6dc9357SAndroid Build Coastguard Worker         if (ext)
381*f6dc9357SAndroid Build Coastguard Worker           type = ext;
382*f6dc9357SAndroid Build Coastguard Worker       }
383*f6dc9357SAndroid Build Coastguard Worker       if (!type.IsEmpty())
384*f6dc9357SAndroid Build Coastguard Worker       {
385*f6dc9357SAndroid Build Coastguard Worker         s.Add_Dot();
386*f6dc9357SAndroid Build Coastguard Worker         s += type;
387*f6dc9357SAndroid Build Coastguard Worker       }
388*f6dc9357SAndroid Build Coastguard Worker       prop = s;
389*f6dc9357SAndroid Build Coastguard Worker       break;
390*f6dc9357SAndroid Build Coastguard Worker     }
391*f6dc9357SAndroid Build Coastguard Worker /*
392*f6dc9357SAndroid Build Coastguard Worker     case kpidCpu:
393*f6dc9357SAndroid Build Coastguard Worker     {
394*f6dc9357SAndroid Build Coastguard Worker       AString s;
395*f6dc9357SAndroid Build Coastguard Worker       s.SetFrom_CalcLen(item.Processor, sizeof(item.Processor));
396*f6dc9357SAndroid Build Coastguard Worker       if (!s.IsEmpty())
397*f6dc9357SAndroid Build Coastguard Worker         prop = s;
398*f6dc9357SAndroid Build Coastguard Worker       break;
399*f6dc9357SAndroid Build Coastguard Worker     }
400*f6dc9357SAndroid Build Coastguard Worker */
401*f6dc9357SAndroid Build Coastguard Worker     case kpidSize:
402*f6dc9357SAndroid Build Coastguard Worker     case kpidPackSize:
403*f6dc9357SAndroid Build Coastguard Worker       prop = BlocksToBytes(item.NumBlocks);
404*f6dc9357SAndroid Build Coastguard Worker       break;
405*f6dc9357SAndroid Build Coastguard Worker     case kpidOffset: prop = BlocksToBytes(item.StartBlock); break;
406*f6dc9357SAndroid Build Coastguard Worker     case kpidCharacts: FLAGS_TO_PROP(k_Flags, item.Flags, prop); break;
407*f6dc9357SAndroid Build Coastguard Worker   }
408*f6dc9357SAndroid Build Coastguard Worker   prop.Detach(value);
409*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
410*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_END
411*f6dc9357SAndroid Build Coastguard Worker }
412*f6dc9357SAndroid Build Coastguard Worker 
413*f6dc9357SAndroid Build Coastguard Worker static const Byte k_Signature[] = { kSig0, kSig1 };
414*f6dc9357SAndroid Build Coastguard Worker 
415*f6dc9357SAndroid Build Coastguard Worker REGISTER_ARC_I(
416*f6dc9357SAndroid Build Coastguard Worker   "APM", "apm", NULL, 0xD4,
417*f6dc9357SAndroid Build Coastguard Worker   k_Signature,
418*f6dc9357SAndroid Build Coastguard Worker   0,
419*f6dc9357SAndroid Build Coastguard Worker   0,
420*f6dc9357SAndroid Build Coastguard Worker   IsArc_Apm)
421*f6dc9357SAndroid Build Coastguard Worker 
422*f6dc9357SAndroid Build Coastguard Worker }}
423