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