1370b324cSopenharmony_ci// LzmaHandler.cpp 2370b324cSopenharmony_ci 3370b324cSopenharmony_ci#include "StdAfx.h" 4370b324cSopenharmony_ci 5370b324cSopenharmony_ci#include "../../../C/CpuArch.h" 6370b324cSopenharmony_ci 7370b324cSopenharmony_ci#include "../../Common/ComTry.h" 8370b324cSopenharmony_ci#include "../../Common/IntToString.h" 9370b324cSopenharmony_ci 10370b324cSopenharmony_ci#include "../../Windows/PropVariant.h" 11370b324cSopenharmony_ci 12370b324cSopenharmony_ci#include "../Common/FilterCoder.h" 13370b324cSopenharmony_ci#include "../Common/ProgressUtils.h" 14370b324cSopenharmony_ci#include "../Common/RegisterArc.h" 15370b324cSopenharmony_ci#include "../Common/StreamUtils.h" 16370b324cSopenharmony_ci 17370b324cSopenharmony_ci#include "../Compress/BcjCoder.h" 18370b324cSopenharmony_ci#include "../Compress/LzmaDecoder.h" 19370b324cSopenharmony_ci 20370b324cSopenharmony_ci#include "Common/DummyOutStream.h" 21370b324cSopenharmony_ci 22370b324cSopenharmony_ciusing namespace NWindows; 23370b324cSopenharmony_ci 24370b324cSopenharmony_cinamespace NArchive { 25370b324cSopenharmony_cinamespace NLzma { 26370b324cSopenharmony_ci 27370b324cSopenharmony_cistatic bool CheckDicSize(const Byte *p) 28370b324cSopenharmony_ci{ 29370b324cSopenharmony_ci UInt32 dicSize = GetUi32(p); 30370b324cSopenharmony_ci if (dicSize == 1) 31370b324cSopenharmony_ci return true; 32370b324cSopenharmony_ci for (unsigned i = 0; i <= 30; i++) 33370b324cSopenharmony_ci if (dicSize == ((UInt32)2 << i) || dicSize == ((UInt32)3 << i)) 34370b324cSopenharmony_ci return true; 35370b324cSopenharmony_ci return (dicSize == 0xFFFFFFFF); 36370b324cSopenharmony_ci} 37370b324cSopenharmony_ci 38370b324cSopenharmony_cistatic const Byte kProps[] = 39370b324cSopenharmony_ci{ 40370b324cSopenharmony_ci kpidSize, 41370b324cSopenharmony_ci kpidPackSize, 42370b324cSopenharmony_ci kpidMethod 43370b324cSopenharmony_ci}; 44370b324cSopenharmony_ci 45370b324cSopenharmony_cistatic const Byte kArcProps[] = 46370b324cSopenharmony_ci{ 47370b324cSopenharmony_ci kpidNumStreams, 48370b324cSopenharmony_ci kpidMethod 49370b324cSopenharmony_ci}; 50370b324cSopenharmony_ci 51370b324cSopenharmony_cistruct CHeader 52370b324cSopenharmony_ci{ 53370b324cSopenharmony_ci UInt64 Size; 54370b324cSopenharmony_ci Byte FilterID; 55370b324cSopenharmony_ci Byte LzmaProps[5]; 56370b324cSopenharmony_ci 57370b324cSopenharmony_ci Byte GetProp() const { return LzmaProps[0]; } 58370b324cSopenharmony_ci UInt32 GetDicSize() const { return GetUi32(LzmaProps + 1); } 59370b324cSopenharmony_ci bool HasSize() const { return (Size != (UInt64)(Int64)-1); } 60370b324cSopenharmony_ci bool Parse(const Byte *buf, bool isThereFilter); 61370b324cSopenharmony_ci}; 62370b324cSopenharmony_ci 63370b324cSopenharmony_cibool CHeader::Parse(const Byte *buf, bool isThereFilter) 64370b324cSopenharmony_ci{ 65370b324cSopenharmony_ci FilterID = 0; 66370b324cSopenharmony_ci if (isThereFilter) 67370b324cSopenharmony_ci FilterID = buf[0]; 68370b324cSopenharmony_ci const Byte *sig = buf + (isThereFilter ? 1 : 0); 69370b324cSopenharmony_ci for (int i = 0; i < 5; i++) 70370b324cSopenharmony_ci LzmaProps[i] = sig[i]; 71370b324cSopenharmony_ci Size = GetUi64(sig + 5); 72370b324cSopenharmony_ci return 73370b324cSopenharmony_ci LzmaProps[0] < 5 * 5 * 9 && 74370b324cSopenharmony_ci FilterID < 2 && 75370b324cSopenharmony_ci (!HasSize() || Size < ((UInt64)1 << 56)) 76370b324cSopenharmony_ci && CheckDicSize(LzmaProps + 1); 77370b324cSopenharmony_ci} 78370b324cSopenharmony_ci 79370b324cSopenharmony_ciclass CDecoder Z7_final 80370b324cSopenharmony_ci{ 81370b324cSopenharmony_ci CMyComPtr<ISequentialOutStream> _bcjStream; 82370b324cSopenharmony_ci CFilterCoder *_filterCoder; 83370b324cSopenharmony_ci CMyComPtr<ICompressCoder> _lzmaDecoder; 84370b324cSopenharmony_cipublic: 85370b324cSopenharmony_ci NCompress::NLzma::CDecoder *_lzmaDecoderSpec; 86370b324cSopenharmony_ci 87370b324cSopenharmony_ci ~CDecoder(); 88370b324cSopenharmony_ci HRESULT Create(bool filtered, ISequentialInStream *inStream); 89370b324cSopenharmony_ci 90370b324cSopenharmony_ci HRESULT Code(const CHeader &header, ISequentialOutStream *outStream, ICompressProgressInfo *progress); 91370b324cSopenharmony_ci 92370b324cSopenharmony_ci UInt64 GetInputProcessedSize() const { return _lzmaDecoderSpec->GetInputProcessedSize(); } 93370b324cSopenharmony_ci 94370b324cSopenharmony_ci void ReleaseInStream() { if (_lzmaDecoder) _lzmaDecoderSpec->ReleaseInStream(); } 95370b324cSopenharmony_ci 96370b324cSopenharmony_ci HRESULT ReadInput(Byte *data, UInt32 size, UInt32 *processedSize) 97370b324cSopenharmony_ci { return _lzmaDecoderSpec->ReadFromInputStream(data, size, processedSize); } 98370b324cSopenharmony_ci}; 99370b324cSopenharmony_ci 100370b324cSopenharmony_ciHRESULT CDecoder::Create(bool filteredMode, ISequentialInStream *inStream) 101370b324cSopenharmony_ci{ 102370b324cSopenharmony_ci if (!_lzmaDecoder) 103370b324cSopenharmony_ci { 104370b324cSopenharmony_ci _lzmaDecoderSpec = new NCompress::NLzma::CDecoder; 105370b324cSopenharmony_ci _lzmaDecoderSpec->FinishStream = true; 106370b324cSopenharmony_ci _lzmaDecoder = _lzmaDecoderSpec; 107370b324cSopenharmony_ci } 108370b324cSopenharmony_ci 109370b324cSopenharmony_ci if (filteredMode) 110370b324cSopenharmony_ci { 111370b324cSopenharmony_ci if (!_bcjStream) 112370b324cSopenharmony_ci { 113370b324cSopenharmony_ci _filterCoder = new CFilterCoder(false); 114370b324cSopenharmony_ci CMyComPtr<ICompressCoder> coder = _filterCoder; 115370b324cSopenharmony_ci _filterCoder->Filter = new NCompress::NBcj::CCoder2(z7_BranchConvSt_X86_Dec); 116370b324cSopenharmony_ci _bcjStream = _filterCoder; 117370b324cSopenharmony_ci } 118370b324cSopenharmony_ci } 119370b324cSopenharmony_ci 120370b324cSopenharmony_ci return _lzmaDecoderSpec->SetInStream(inStream); 121370b324cSopenharmony_ci} 122370b324cSopenharmony_ci 123370b324cSopenharmony_ciCDecoder::~CDecoder() 124370b324cSopenharmony_ci{ 125370b324cSopenharmony_ci ReleaseInStream(); 126370b324cSopenharmony_ci} 127370b324cSopenharmony_ci 128370b324cSopenharmony_ciHRESULT CDecoder::Code(const CHeader &header, ISequentialOutStream *outStream, 129370b324cSopenharmony_ci ICompressProgressInfo *progress) 130370b324cSopenharmony_ci{ 131370b324cSopenharmony_ci if (header.FilterID > 1) 132370b324cSopenharmony_ci return E_NOTIMPL; 133370b324cSopenharmony_ci 134370b324cSopenharmony_ci RINOK(_lzmaDecoderSpec->SetDecoderProperties2(header.LzmaProps, 5)) 135370b324cSopenharmony_ci 136370b324cSopenharmony_ci bool filteredMode = (header.FilterID == 1); 137370b324cSopenharmony_ci 138370b324cSopenharmony_ci if (filteredMode) 139370b324cSopenharmony_ci { 140370b324cSopenharmony_ci RINOK(_filterCoder->SetOutStream(outStream)) 141370b324cSopenharmony_ci outStream = _bcjStream; 142370b324cSopenharmony_ci RINOK(_filterCoder->SetOutStreamSize(NULL)) 143370b324cSopenharmony_ci } 144370b324cSopenharmony_ci 145370b324cSopenharmony_ci const UInt64 *Size = header.HasSize() ? &header.Size : NULL; 146370b324cSopenharmony_ci HRESULT res = _lzmaDecoderSpec->CodeResume(outStream, Size, progress); 147370b324cSopenharmony_ci 148370b324cSopenharmony_ci if (filteredMode) 149370b324cSopenharmony_ci { 150370b324cSopenharmony_ci { 151370b324cSopenharmony_ci HRESULT res2 = _filterCoder->OutStreamFinish(); 152370b324cSopenharmony_ci if (res == S_OK) 153370b324cSopenharmony_ci res = res2; 154370b324cSopenharmony_ci } 155370b324cSopenharmony_ci HRESULT res2 = _filterCoder->ReleaseOutStream(); 156370b324cSopenharmony_ci if (res == S_OK) 157370b324cSopenharmony_ci res = res2; 158370b324cSopenharmony_ci } 159370b324cSopenharmony_ci 160370b324cSopenharmony_ci RINOK(res) 161370b324cSopenharmony_ci 162370b324cSopenharmony_ci if (header.HasSize()) 163370b324cSopenharmony_ci if (_lzmaDecoderSpec->GetOutputProcessedSize() != header.Size) 164370b324cSopenharmony_ci return S_FALSE; 165370b324cSopenharmony_ci 166370b324cSopenharmony_ci return S_OK; 167370b324cSopenharmony_ci} 168370b324cSopenharmony_ci 169370b324cSopenharmony_ci 170370b324cSopenharmony_ciZ7_CLASS_IMP_CHandler_IInArchive_1( 171370b324cSopenharmony_ci IArchiveOpenSeq 172370b324cSopenharmony_ci) 173370b324cSopenharmony_ci CHeader _header; 174370b324cSopenharmony_ci bool _lzma86; 175370b324cSopenharmony_ci CMyComPtr<IInStream> _stream; 176370b324cSopenharmony_ci CMyComPtr<ISequentialInStream> _seqStream; 177370b324cSopenharmony_ci 178370b324cSopenharmony_ci bool _isArc; 179370b324cSopenharmony_ci bool _needSeekToStart; 180370b324cSopenharmony_ci bool _dataAfterEnd; 181370b324cSopenharmony_ci bool _needMoreInput; 182370b324cSopenharmony_ci bool _unsupported; 183370b324cSopenharmony_ci bool _dataError; 184370b324cSopenharmony_ci 185370b324cSopenharmony_ci bool _packSize_Defined; 186370b324cSopenharmony_ci bool _unpackSize_Defined; 187370b324cSopenharmony_ci bool _numStreams_Defined; 188370b324cSopenharmony_ci 189370b324cSopenharmony_ci UInt64 _packSize; 190370b324cSopenharmony_ci UInt64 _unpackSize; 191370b324cSopenharmony_ci UInt64 _numStreams; 192370b324cSopenharmony_ci 193370b324cSopenharmony_ci void GetMethod(NCOM::CPropVariant &prop); 194370b324cSopenharmony_ci 195370b324cSopenharmony_ci unsigned GetHeaderSize() const { return 5 + 8 + (_lzma86 ? 1 : 0); } 196370b324cSopenharmony_cipublic: 197370b324cSopenharmony_ci CHandler(bool lzma86) { _lzma86 = lzma86; } 198370b324cSopenharmony_ci}; 199370b324cSopenharmony_ci 200370b324cSopenharmony_ciIMP_IInArchive_Props 201370b324cSopenharmony_ciIMP_IInArchive_ArcProps 202370b324cSopenharmony_ci 203370b324cSopenharmony_ciZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)) 204370b324cSopenharmony_ci{ 205370b324cSopenharmony_ci NCOM::CPropVariant prop; 206370b324cSopenharmony_ci switch (propID) 207370b324cSopenharmony_ci { 208370b324cSopenharmony_ci case kpidPhySize: if (_packSize_Defined) prop = _packSize; break; 209370b324cSopenharmony_ci case kpidNumStreams: if (_numStreams_Defined) prop = _numStreams; break; 210370b324cSopenharmony_ci case kpidUnpackSize: if (_unpackSize_Defined) prop = _unpackSize; break; 211370b324cSopenharmony_ci case kpidMethod: GetMethod(prop); break; 212370b324cSopenharmony_ci case kpidErrorFlags: 213370b324cSopenharmony_ci { 214370b324cSopenharmony_ci UInt32 v = 0; 215370b324cSopenharmony_ci if (!_isArc) v |= kpv_ErrorFlags_IsNotArc; 216370b324cSopenharmony_ci if (_needMoreInput) v |= kpv_ErrorFlags_UnexpectedEnd; 217370b324cSopenharmony_ci if (_dataAfterEnd) v |= kpv_ErrorFlags_DataAfterEnd; 218370b324cSopenharmony_ci if (_unsupported) v |= kpv_ErrorFlags_UnsupportedMethod; 219370b324cSopenharmony_ci if (_dataError) v |= kpv_ErrorFlags_DataError; 220370b324cSopenharmony_ci prop = v; 221370b324cSopenharmony_ci break; 222370b324cSopenharmony_ci } 223370b324cSopenharmony_ci } 224370b324cSopenharmony_ci prop.Detach(value); 225370b324cSopenharmony_ci return S_OK; 226370b324cSopenharmony_ci} 227370b324cSopenharmony_ci 228370b324cSopenharmony_ciZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems)) 229370b324cSopenharmony_ci{ 230370b324cSopenharmony_ci *numItems = 1; 231370b324cSopenharmony_ci return S_OK; 232370b324cSopenharmony_ci} 233370b324cSopenharmony_ci 234370b324cSopenharmony_ci 235370b324cSopenharmony_cistatic char * DictSizeToString(UInt32 val, char *s) 236370b324cSopenharmony_ci{ 237370b324cSopenharmony_ci for (unsigned i = 0; i < 32; i++) 238370b324cSopenharmony_ci if (((UInt32)1 << i) == val) 239370b324cSopenharmony_ci return ::ConvertUInt32ToString(i, s); 240370b324cSopenharmony_ci char c = 'b'; 241370b324cSopenharmony_ci if ((val & ((1 << 20) - 1)) == 0) { val >>= 20; c = 'm'; } 242370b324cSopenharmony_ci else if ((val & ((1 << 10) - 1)) == 0) { val >>= 10; c = 'k'; } 243370b324cSopenharmony_ci s = ::ConvertUInt32ToString(val, s); 244370b324cSopenharmony_ci *s++ = c; 245370b324cSopenharmony_ci *s = 0; 246370b324cSopenharmony_ci return s; 247370b324cSopenharmony_ci} 248370b324cSopenharmony_ci 249370b324cSopenharmony_cistatic char *AddProp32(char *s, const char *name, UInt32 v) 250370b324cSopenharmony_ci{ 251370b324cSopenharmony_ci *s++ = ':'; 252370b324cSopenharmony_ci s = MyStpCpy(s, name); 253370b324cSopenharmony_ci return ::ConvertUInt32ToString(v, s); 254370b324cSopenharmony_ci} 255370b324cSopenharmony_ci 256370b324cSopenharmony_civoid CHandler::GetMethod(NCOM::CPropVariant &prop) 257370b324cSopenharmony_ci{ 258370b324cSopenharmony_ci if (!_stream) 259370b324cSopenharmony_ci return; 260370b324cSopenharmony_ci 261370b324cSopenharmony_ci char sz[64]; 262370b324cSopenharmony_ci char *s = sz; 263370b324cSopenharmony_ci if (_header.FilterID != 0) 264370b324cSopenharmony_ci s = MyStpCpy(s, "BCJ "); 265370b324cSopenharmony_ci s = MyStpCpy(s, "LZMA:"); 266370b324cSopenharmony_ci s = DictSizeToString(_header.GetDicSize(), s); 267370b324cSopenharmony_ci 268370b324cSopenharmony_ci UInt32 d = _header.GetProp(); 269370b324cSopenharmony_ci // if (d != 0x5D) 270370b324cSopenharmony_ci { 271370b324cSopenharmony_ci UInt32 lc = d % 9; 272370b324cSopenharmony_ci d /= 9; 273370b324cSopenharmony_ci UInt32 pb = d / 5; 274370b324cSopenharmony_ci UInt32 lp = d % 5; 275370b324cSopenharmony_ci if (lc != 3) s = AddProp32(s, "lc", lc); 276370b324cSopenharmony_ci if (lp != 0) s = AddProp32(s, "lp", lp); 277370b324cSopenharmony_ci if (pb != 2) s = AddProp32(s, "pb", pb); 278370b324cSopenharmony_ci } 279370b324cSopenharmony_ci prop = sz; 280370b324cSopenharmony_ci} 281370b324cSopenharmony_ci 282370b324cSopenharmony_ci 283370b324cSopenharmony_ciZ7_COM7F_IMF(CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)) 284370b324cSopenharmony_ci{ 285370b324cSopenharmony_ci NCOM::CPropVariant prop; 286370b324cSopenharmony_ci switch (propID) 287370b324cSopenharmony_ci { 288370b324cSopenharmony_ci case kpidSize: if (_stream && _header.HasSize()) prop = _header.Size; break; 289370b324cSopenharmony_ci case kpidPackSize: if (_packSize_Defined) prop = _packSize; break; 290370b324cSopenharmony_ci case kpidMethod: GetMethod(prop); break; 291370b324cSopenharmony_ci } 292370b324cSopenharmony_ci prop.Detach(value); 293370b324cSopenharmony_ci return S_OK; 294370b324cSopenharmony_ci} 295370b324cSopenharmony_ci 296370b324cSopenharmony_ciAPI_FUNC_static_IsArc IsArc_Lzma(const Byte *p, size_t size) 297370b324cSopenharmony_ci{ 298370b324cSopenharmony_ci const UInt32 kHeaderSize = 1 + 4 + 8; 299370b324cSopenharmony_ci if (size < kHeaderSize) 300370b324cSopenharmony_ci return k_IsArc_Res_NEED_MORE; 301370b324cSopenharmony_ci if (p[0] >= 5 * 5 * 9) 302370b324cSopenharmony_ci return k_IsArc_Res_NO; 303370b324cSopenharmony_ci const UInt64 unpackSize = GetUi64(p + 1 + 4); 304370b324cSopenharmony_ci if (unpackSize != (UInt64)(Int64)-1) 305370b324cSopenharmony_ci { 306370b324cSopenharmony_ci if (unpackSize >= ((UInt64)1 << 56)) 307370b324cSopenharmony_ci return k_IsArc_Res_NO; 308370b324cSopenharmony_ci } 309370b324cSopenharmony_ci if (unpackSize != 0) 310370b324cSopenharmony_ci { 311370b324cSopenharmony_ci if (size < kHeaderSize + 2) 312370b324cSopenharmony_ci return k_IsArc_Res_NEED_MORE; 313370b324cSopenharmony_ci if (p[kHeaderSize] != 0) 314370b324cSopenharmony_ci return k_IsArc_Res_NO; 315370b324cSopenharmony_ci if (unpackSize != (UInt64)(Int64)-1) 316370b324cSopenharmony_ci { 317370b324cSopenharmony_ci if ((p[kHeaderSize + 1] & 0x80) != 0) 318370b324cSopenharmony_ci return k_IsArc_Res_NO; 319370b324cSopenharmony_ci } 320370b324cSopenharmony_ci } 321370b324cSopenharmony_ci if (!CheckDicSize(p + 1)) 322370b324cSopenharmony_ci // return k_IsArc_Res_YES_LOW_PROB; 323370b324cSopenharmony_ci return k_IsArc_Res_NO; 324370b324cSopenharmony_ci return k_IsArc_Res_YES; 325370b324cSopenharmony_ci} 326370b324cSopenharmony_ci} 327370b324cSopenharmony_ci 328370b324cSopenharmony_ciAPI_FUNC_static_IsArc IsArc_Lzma86(const Byte *p, size_t size) 329370b324cSopenharmony_ci{ 330370b324cSopenharmony_ci if (size < 1) 331370b324cSopenharmony_ci return k_IsArc_Res_NEED_MORE; 332370b324cSopenharmony_ci Byte filterID = p[0]; 333370b324cSopenharmony_ci if (filterID != 0 && filterID != 1) 334370b324cSopenharmony_ci return k_IsArc_Res_NO; 335370b324cSopenharmony_ci return IsArc_Lzma(p + 1, size - 1); 336370b324cSopenharmony_ci} 337370b324cSopenharmony_ci} 338370b324cSopenharmony_ci 339370b324cSopenharmony_ci 340370b324cSopenharmony_ci 341370b324cSopenharmony_ciZ7_COM7F_IMF(CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *)) 342370b324cSopenharmony_ci{ 343370b324cSopenharmony_ci Close(); 344370b324cSopenharmony_ci 345370b324cSopenharmony_ci const unsigned headerSize = GetHeaderSize(); 346370b324cSopenharmony_ci const UInt32 kBufSize = 1 << 7; 347370b324cSopenharmony_ci Byte buf[kBufSize]; 348370b324cSopenharmony_ci size_t processedSize = kBufSize; 349370b324cSopenharmony_ci RINOK(ReadStream(inStream, buf, &processedSize)) 350370b324cSopenharmony_ci if (processedSize < headerSize + 2) 351370b324cSopenharmony_ci return S_FALSE; 352370b324cSopenharmony_ci if (!_header.Parse(buf, _lzma86)) 353370b324cSopenharmony_ci return S_FALSE; 354370b324cSopenharmony_ci const Byte *start = buf + headerSize; 355370b324cSopenharmony_ci if (start[0] != 0 /* || (start[1] & 0x80) != 0 */ ) // empty stream with EOS is not 0x80 356370b324cSopenharmony_ci return S_FALSE; 357370b324cSopenharmony_ci 358370b324cSopenharmony_ci RINOK(InStream_GetSize_SeekToEnd(inStream, _packSize)) 359370b324cSopenharmony_ci 360370b324cSopenharmony_ci SizeT srcLen = (SizeT)processedSize - headerSize; 361370b324cSopenharmony_ci 362370b324cSopenharmony_ci if (srcLen > 10 363370b324cSopenharmony_ci && _header.Size == 0 364370b324cSopenharmony_ci // && _header.FilterID == 0 365370b324cSopenharmony_ci && _header.LzmaProps[0] == 0 366370b324cSopenharmony_ci ) 367370b324cSopenharmony_ci return S_FALSE; 368370b324cSopenharmony_ci 369370b324cSopenharmony_ci CDecoder state; 370370b324cSopenharmony_ci const UInt32 outLimit = 1 << 11; 371370b324cSopenharmony_ci Byte outBuf[outLimit]; 372370b324cSopenharmony_ci 373370b324cSopenharmony_ci SizeT outSize = outLimit; 374370b324cSopenharmony_ci if (outSize > _header.Size) 375370b324cSopenharmony_ci outSize = (SizeT)_header.Size; 376370b324cSopenharmony_ci SizeT destLen = outSize; 377370b324cSopenharmony_ci ELzmaStatus status; 378370b324cSopenharmony_ci 379370b324cSopenharmony_ci SRes res = LzmaDecode(outBuf, &destLen, start, &srcLen, 380370b324cSopenharmony_ci _header.LzmaProps, 5, LZMA_FINISH_ANY, 381370b324cSopenharmony_ci &status, &g_Alloc); 382370b324cSopenharmony_ci 383370b324cSopenharmony_ci if (res != SZ_OK) 384370b324cSopenharmony_ci if (res != SZ_ERROR_INPUT_EOF) 385370b324cSopenharmony_ci return S_FALSE; 386370b324cSopenharmony_ci 387370b324cSopenharmony_ci _isArc = true; 388370b324cSopenharmony_ci _stream = inStream; 389370b324cSopenharmony_ci _seqStream = inStream; 390370b324cSopenharmony_ci _needSeekToStart = true; 391370b324cSopenharmony_ci return S_OK; 392370b324cSopenharmony_ci} 393370b324cSopenharmony_ci 394370b324cSopenharmony_ciZ7_COM7F_IMF(CHandler::OpenSeq(ISequentialInStream *stream)) 395370b324cSopenharmony_ci{ 396370b324cSopenharmony_ci Close(); 397370b324cSopenharmony_ci _isArc = true; 398370b324cSopenharmony_ci _seqStream = stream; 399370b324cSopenharmony_ci return S_OK; 400370b324cSopenharmony_ci} 401370b324cSopenharmony_ci 402370b324cSopenharmony_ciZ7_COM7F_IMF(CHandler::Close()) 403370b324cSopenharmony_ci{ 404370b324cSopenharmony_ci _isArc = false; 405370b324cSopenharmony_ci _needSeekToStart = false; 406370b324cSopenharmony_ci _dataAfterEnd = false; 407370b324cSopenharmony_ci _needMoreInput = false; 408370b324cSopenharmony_ci _unsupported = false; 409370b324cSopenharmony_ci _dataError = false; 410370b324cSopenharmony_ci 411370b324cSopenharmony_ci _packSize_Defined = false; 412370b324cSopenharmony_ci _unpackSize_Defined = false; 413370b324cSopenharmony_ci _numStreams_Defined = false; 414370b324cSopenharmony_ci 415370b324cSopenharmony_ci _packSize = 0; 416370b324cSopenharmony_ci 417370b324cSopenharmony_ci _stream.Release(); 418370b324cSopenharmony_ci _seqStream.Release(); 419370b324cSopenharmony_ci return S_OK; 420370b324cSopenharmony_ci} 421370b324cSopenharmony_ci 422370b324cSopenharmony_ciZ7_CLASS_IMP_COM_1( 423370b324cSopenharmony_ci CCompressProgressInfoImp, 424370b324cSopenharmony_ci ICompressProgressInfo 425370b324cSopenharmony_ci) 426370b324cSopenharmony_ci CMyComPtr<IArchiveOpenCallback> Callback; 427370b324cSopenharmony_cipublic: 428370b324cSopenharmony_ci UInt64 Offset; 429370b324cSopenharmony_ci 430370b324cSopenharmony_ci void Init(IArchiveOpenCallback *callback) { Callback = callback; } 431370b324cSopenharmony_ci}; 432370b324cSopenharmony_ci 433370b324cSopenharmony_ciZ7_COM7F_IMF(CCompressProgressInfoImp::SetRatioInfo(const UInt64 *inSize, const UInt64 * /* outSize */)) 434370b324cSopenharmony_ci{ 435370b324cSopenharmony_ci if (Callback) 436370b324cSopenharmony_ci { 437370b324cSopenharmony_ci const UInt64 files = 0; 438370b324cSopenharmony_ci const UInt64 val = Offset + *inSize; 439370b324cSopenharmony_ci return Callback->SetCompleted(&files, &val); 440370b324cSopenharmony_ci } 441370b324cSopenharmony_ci return S_OK; 442370b324cSopenharmony_ci} 443370b324cSopenharmony_ci 444370b324cSopenharmony_ciZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, 445370b324cSopenharmony_ci Int32 testMode, IArchiveExtractCallback *extractCallback)) 446370b324cSopenharmony_ci{ 447370b324cSopenharmony_ci COM_TRY_BEGIN 448370b324cSopenharmony_ci 449370b324cSopenharmony_ci if (numItems == 0) 450370b324cSopenharmony_ci return S_OK; 451370b324cSopenharmony_ci if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0)) 452370b324cSopenharmony_ci return E_INVALIDARG; 453370b324cSopenharmony_ci 454370b324cSopenharmony_ci if (_packSize_Defined) 455370b324cSopenharmony_ci extractCallback->SetTotal(_packSize); 456370b324cSopenharmony_ci 457370b324cSopenharmony_ci 458370b324cSopenharmony_ci CMyComPtr<ISequentialOutStream> realOutStream; 459370b324cSopenharmony_ci const Int32 askMode = testMode ? 460370b324cSopenharmony_ci NExtract::NAskMode::kTest : 461370b324cSopenharmony_ci NExtract::NAskMode::kExtract; 462370b324cSopenharmony_ci RINOK(extractCallback->GetStream(0, &realOutStream, askMode)) 463370b324cSopenharmony_ci if (!testMode && !realOutStream) 464370b324cSopenharmony_ci return S_OK; 465370b324cSopenharmony_ci 466370b324cSopenharmony_ci extractCallback->PrepareOperation(askMode); 467370b324cSopenharmony_ci 468370b324cSopenharmony_ci CDummyOutStream *outStreamSpec = new CDummyOutStream; 469370b324cSopenharmony_ci CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); 470370b324cSopenharmony_ci outStreamSpec->SetStream(realOutStream); 471370b324cSopenharmony_ci outStreamSpec->Init(); 472370b324cSopenharmony_ci realOutStream.Release(); 473370b324cSopenharmony_ci 474370b324cSopenharmony_ci CLocalProgress *lps = new CLocalProgress; 475370b324cSopenharmony_ci CMyComPtr<ICompressProgressInfo> progress = lps; 476370b324cSopenharmony_ci lps->Init(extractCallback, true); 477370b324cSopenharmony_ci 478370b324cSopenharmony_ci if (_needSeekToStart) 479370b324cSopenharmony_ci { 480370b324cSopenharmony_ci if (!_stream) 481370b324cSopenharmony_ci return E_FAIL; 482370b324cSopenharmony_ci RINOK(InStream_SeekToBegin(_stream)) 483370b324cSopenharmony_ci } 484370b324cSopenharmony_ci else 485370b324cSopenharmony_ci _needSeekToStart = true; 486370b324cSopenharmony_ci 487370b324cSopenharmony_ci CDecoder decoder; 488370b324cSopenharmony_ci HRESULT result = decoder.Create(_lzma86, _seqStream); 489370b324cSopenharmony_ci RINOK(result) 490370b324cSopenharmony_ci 491370b324cSopenharmony_ci bool firstItem = true; 492370b324cSopenharmony_ci 493370b324cSopenharmony_ci UInt64 packSize = 0; 494370b324cSopenharmony_ci UInt64 unpackSize = 0; 495370b324cSopenharmony_ci UInt64 numStreams = 0; 496370b324cSopenharmony_ci 497370b324cSopenharmony_ci bool dataAfterEnd = false; 498370b324cSopenharmony_ci 499370b324cSopenharmony_ci for (;;) 500370b324cSopenharmony_ci { 501370b324cSopenharmony_ci lps->InSize = packSize; 502370b324cSopenharmony_ci lps->OutSize = unpackSize; 503370b324cSopenharmony_ci RINOK(lps->SetCur()) 504370b324cSopenharmony_ci 505370b324cSopenharmony_ci const UInt32 kBufSize = 1 + 5 + 8; 506370b324cSopenharmony_ci Byte buf[kBufSize]; 507370b324cSopenharmony_ci const UInt32 headerSize = GetHeaderSize(); 508370b324cSopenharmony_ci UInt32 processed; 509370b324cSopenharmony_ci RINOK(decoder.ReadInput(buf, headerSize, &processed)) 510370b324cSopenharmony_ci if (processed != headerSize) 511370b324cSopenharmony_ci { 512370b324cSopenharmony_ci if (processed != 0) 513370b324cSopenharmony_ci dataAfterEnd = true; 514370b324cSopenharmony_ci break; 515370b324cSopenharmony_ci } 516370b324cSopenharmony_ci 517370b324cSopenharmony_ci CHeader st; 518370b324cSopenharmony_ci if (!st.Parse(buf, _lzma86)) 519370b324cSopenharmony_ci { 520370b324cSopenharmony_ci dataAfterEnd = true; 521370b324cSopenharmony_ci break; 522370b324cSopenharmony_ci } 523370b324cSopenharmony_ci numStreams++; 524370b324cSopenharmony_ci firstItem = false; 525370b324cSopenharmony_ci 526370b324cSopenharmony_ci result = decoder.Code(st, outStream, progress); 527370b324cSopenharmony_ci 528370b324cSopenharmony_ci packSize = decoder.GetInputProcessedSize(); 529370b324cSopenharmony_ci unpackSize = outStreamSpec->GetSize(); 530370b324cSopenharmony_ci 531370b324cSopenharmony_ci if (result == E_NOTIMPL) 532370b324cSopenharmony_ci { 533370b324cSopenharmony_ci _unsupported = true; 534370b324cSopenharmony_ci result = S_FALSE; 535370b324cSopenharmony_ci break; 536370b324cSopenharmony_ci } 537370b324cSopenharmony_ci if (result == S_FALSE) 538370b324cSopenharmony_ci break; 539370b324cSopenharmony_ci RINOK(result) 540370b324cSopenharmony_ci } 541370b324cSopenharmony_ci 542370b324cSopenharmony_ci if (firstItem) 543370b324cSopenharmony_ci { 544370b324cSopenharmony_ci _isArc = false; 545370b324cSopenharmony_ci result = S_FALSE; 546370b324cSopenharmony_ci } 547370b324cSopenharmony_ci else if (result == S_OK || result == S_FALSE) 548370b324cSopenharmony_ci { 549370b324cSopenharmony_ci if (dataAfterEnd) 550370b324cSopenharmony_ci _dataAfterEnd = true; 551370b324cSopenharmony_ci else if (decoder._lzmaDecoderSpec->NeedsMoreInput()) 552370b324cSopenharmony_ci _needMoreInput = true; 553370b324cSopenharmony_ci 554370b324cSopenharmony_ci _packSize = packSize; 555370b324cSopenharmony_ci _unpackSize = unpackSize; 556370b324cSopenharmony_ci _numStreams = numStreams; 557370b324cSopenharmony_ci 558370b324cSopenharmony_ci _packSize_Defined = true; 559370b324cSopenharmony_ci _unpackSize_Defined = true; 560370b324cSopenharmony_ci _numStreams_Defined = true; 561370b324cSopenharmony_ci } 562370b324cSopenharmony_ci 563370b324cSopenharmony_ci Int32 opResult = NExtract::NOperationResult::kOK; 564370b324cSopenharmony_ci 565370b324cSopenharmony_ci if (!_isArc) 566370b324cSopenharmony_ci opResult = NExtract::NOperationResult::kIsNotArc; 567370b324cSopenharmony_ci else if (_needMoreInput) 568370b324cSopenharmony_ci opResult = NExtract::NOperationResult::kUnexpectedEnd; 569370b324cSopenharmony_ci else if (_unsupported) 570370b324cSopenharmony_ci opResult = NExtract::NOperationResult::kUnsupportedMethod; 571370b324cSopenharmony_ci else if (_dataAfterEnd) 572370b324cSopenharmony_ci opResult = NExtract::NOperationResult::kDataAfterEnd; 573370b324cSopenharmony_ci else if (result == S_FALSE) 574370b324cSopenharmony_ci opResult = NExtract::NOperationResult::kDataError; 575370b324cSopenharmony_ci else if (result == S_OK) 576370b324cSopenharmony_ci opResult = NExtract::NOperationResult::kOK; 577370b324cSopenharmony_ci else 578370b324cSopenharmony_ci return result; 579370b324cSopenharmony_ci 580370b324cSopenharmony_ci outStream.Release(); 581370b324cSopenharmony_ci return extractCallback->SetOperationResult(opResult); 582370b324cSopenharmony_ci 583370b324cSopenharmony_ci COM_TRY_END 584370b324cSopenharmony_ci} 585370b324cSopenharmony_ci 586370b324cSopenharmony_cinamespace NLzmaAr { 587370b324cSopenharmony_ci 588370b324cSopenharmony_ci// 2, { 0x5D, 0x00 }, 589370b324cSopenharmony_ci 590370b324cSopenharmony_ciREGISTER_ARC_I_CLS_NO_SIG( 591370b324cSopenharmony_ci CHandler(false), 592370b324cSopenharmony_ci "lzma", "lzma", NULL, 0xA, 593370b324cSopenharmony_ci 0, 594370b324cSopenharmony_ci NArcInfoFlags::kStartOpen | 595370b324cSopenharmony_ci NArcInfoFlags::kKeepName, 596370b324cSopenharmony_ci IsArc_Lzma) 597370b324cSopenharmony_ci 598370b324cSopenharmony_ci} 599370b324cSopenharmony_ci 600370b324cSopenharmony_cinamespace NLzma86Ar { 601370b324cSopenharmony_ci 602370b324cSopenharmony_ciREGISTER_ARC_I_CLS_NO_SIG( 603370b324cSopenharmony_ci CHandler(true), 604370b324cSopenharmony_ci "lzma86", "lzma86", NULL, 0xB, 605370b324cSopenharmony_ci 0, 606370b324cSopenharmony_ci NArcInfoFlags::kKeepName, 607370b324cSopenharmony_ci IsArc_Lzma86) 608370b324cSopenharmony_ci 609370b324cSopenharmony_ci} 610370b324cSopenharmony_ci 611370b324cSopenharmony_ci}} 612