HRESULT CInArchive::ReadDatabase2( DECL_EXTERNAL_CODECS_LOC_VARS CArchiveDatabaseEx &db #ifndef _NO_CRYPTO , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined #endif ) { db.Clear(); db.ArchiveInfo.StartPosition = _arhiveBeginStreamPosition; db.ArchiveInfo.Version.Major = _header[6]; db.ArchiveInfo.Version.Minor = _header[7]; if (db.ArchiveInfo.Version.Major != kMajorVersion) ThrowUnsupportedVersion(); UInt32 crcFromArchive = Get32(_header + 8); UInt64 nextHeaderOffset = Get64(_header + 0xC); UInt64 nextHeaderSize = Get64(_header + 0x14); UInt32 nextHeaderCRC = Get32(_header + 0x1C); UInt32 crc = CrcCalc(_header + 0xC, 20); #ifdef FORMAT_7Z_RECOVERY if (crcFromArchive == 0 && nextHeaderOffset == 0 && nextHeaderSize == 0 && nextHeaderCRC == 0) { UInt64 cur, cur2; RINOK(_stream->Seek(0, STREAM_SEEK_CUR, &cur)); const int kCheckSize = 500; Byte buf[kCheckSize]; RINOK(_stream->Seek(0, STREAM_SEEK_END, &cur2)); int checkSize = kCheckSize; if (cur2 - cur < kCheckSize) checkSize = (int)(cur2 - cur); RINOK(_stream->Seek(-checkSize, STREAM_SEEK_END, &cur2)); RINOK(ReadStream_FALSE(_stream, buf, (size_t)checkSize)); int i; for (i = (int)checkSize - 2; i >= 0; i--) if (buf[i] == 0x17 && buf[i + 1] == 0x6 || buf[i] == 0x01 && buf[i + 1] == 0x04) break; if (i < 0) return S_FALSE; nextHeaderSize = checkSize - i; nextHeaderOffset = cur2 - cur + i; nextHeaderCRC = CrcCalc(buf + i, (size_t)nextHeaderSize); RINOK(_stream->Seek(cur, STREAM_SEEK_SET, NULL)); } else #endif { if (crc != crcFromArchive) ThrowIncorrect(); } db.ArchiveInfo.StartPositionAfterHeader = _arhiveBeginStreamPosition + kHeaderSize; if (nextHeaderSize == 0) return S_OK; if (nextHeaderSize > (UInt64)0xFFFFFFFF) return S_FALSE; if ((Int64)nextHeaderOffset < 0) return S_FALSE; RINOK(_stream->Seek(nextHeaderOffset, STREAM_SEEK_CUR, NULL)); CByteBuffer buffer2; buffer2.SetCapacity((size_t)nextHeaderSize); RINOK(ReadStream_FALSE(_stream, buffer2, (size_t)nextHeaderSize)); HeadersSize += kHeaderSize + nextHeaderSize; db.PhySize = kHeaderSize + nextHeaderOffset + nextHeaderSize; if (CrcCalc(buffer2, (UInt32)nextHeaderSize) != nextHeaderCRC) ThrowIncorrect(); CStreamSwitch streamSwitch; streamSwitch.Set(this, buffer2); CObjectVector<CByteBuffer> dataVector; UInt64 type = ReadID(); if (type != NID::kHeader) { if (type != NID::kEncodedHeader) ThrowIncorrect(); HRESULT result = ReadAndDecodePackedStreams( EXTERNAL_CODECS_LOC_VARS db.ArchiveInfo.StartPositionAfterHeader, db.ArchiveInfo.DataStartPosition2, dataVector #ifndef _NO_CRYPTO , getTextPassword, passwordIsDefined #endif ); RINOK(result); if (dataVector.Size() == 0) return S_OK; if (dataVector.Size() > 1) ThrowIncorrect(); streamSwitch.Remove(); streamSwitch.Set(this, dataVector.Front()); if (ReadID() != NID::kHeader) ThrowIncorrect(); } db.HeadersSize = HeadersSize; return ReadHeader( EXTERNAL_CODECS_LOC_VARS db #ifndef _NO_CRYPTO , getTextPassword, passwordIsDefined #endif ); }
STDMETHODIMP CCoderMixer2ST::Code(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, ICompressProgressInfo *progress) { if (numInStreams != (UInt32)_bindInfo.InStreams.Size() || numOutStreams != (UInt32)_bindInfo.OutStreams.Size()) return E_INVALIDARG; // Find main coder int _mainCoderIndex = -1; int i; for (i = 0; i < _coders.Size(); i++) if (_coders[i].IsMain) { _mainCoderIndex = i; break; } if (_mainCoderIndex < 0) for (i = 0; i < _coders.Size(); i++) if (_coders[i].NumInStreams > 1) { if (_mainCoderIndex >= 0) return E_NOTIMPL; _mainCoderIndex = i; } if (_mainCoderIndex < 0) _mainCoderIndex = 0; // _mainCoderIndex = 0; // _mainCoderIndex = _coders.Size() - 1; CCoderInfo &mainCoder = _coders[_mainCoderIndex]; CObjectVector< CMyComPtr<ISequentialInStream> > seqInStreams; CObjectVector< CMyComPtr<ISequentialOutStream> > seqOutStreams; UInt32 startInIndex = _bindInfo.GetCoderInStreamIndex(_mainCoderIndex); UInt32 startOutIndex = _bindInfo.GetCoderOutStreamIndex(_mainCoderIndex); for (i = 0; i < (int)mainCoder.NumInStreams; i++) { CMyComPtr<ISequentialInStream> seqInStream; RINOK(GetInStream(inStreams, inSizes, startInIndex + i, &seqInStream)); seqInStreams.Add(seqInStream); } for (i = 0; i < (int)mainCoder.NumOutStreams; i++) { CMyComPtr<ISequentialOutStream> seqOutStream; RINOK(GetOutStream(outStreams, outSizes, startOutIndex + i, &seqOutStream)); seqOutStreams.Add(seqOutStream); } CRecordVector< ISequentialInStream * > seqInStreamsSpec; CRecordVector< ISequentialOutStream * > seqOutStreamsSpec; for (i = 0; i < (int)mainCoder.NumInStreams; i++) seqInStreamsSpec.Add(seqInStreams[i]); for (i = 0; i < (int)mainCoder.NumOutStreams; i++) seqOutStreamsSpec.Add(seqOutStreams[i]); for (i = 0; i < _coders.Size(); i++) { if (i == _mainCoderIndex) continue; CCoderInfo &coder = _coders[i]; CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize; coder.Coder.QueryInterface(IID_ICompressSetOutStreamSize, &setOutStreamSize); if (setOutStreamSize) { RINOK(setOutStreamSize->SetOutStreamSize(coder.OutSizePointers[0])); } } if (mainCoder.Coder) { RINOK(mainCoder.Coder->Code( seqInStreamsSpec[0], seqOutStreamsSpec[0], mainCoder.InSizePointers[0], mainCoder.OutSizePointers[0], progress)); } else { RINOK(mainCoder.Coder2->Code( &seqInStreamsSpec.Front(), &mainCoder.InSizePointers.Front(), mainCoder.NumInStreams, &seqOutStreamsSpec.Front(), &mainCoder.OutSizePointers.Front(), mainCoder.NumOutStreams, progress)); } CMyComPtr<IOutStreamFlush> flush; seqOutStreams.Front().QueryInterface(IID_IOutStreamFlush, &flush); if (flush) return flush->Flush(); return S_OK; }