STDMETHODIMP CHandler::Extract(const quint32* indices, quint32 numItems, qint32 _aTestMode, IArchiveExtractCallback *extractCallback) { RefPtr<IArchiveExtractCallback> kungFuGrip(extractCallback); CZipDecoder myDecoder; bool testMode = (_aTestMode != 0); quint64 totalUnPacked = 0, totalPacked = 0; bool allFilesMode = (numItems == quint32(-1)); if (allFilesMode) numItems = m_Items.size(); if (numItems == 0) return S_OK; quint32 i; for (i = 0; i < numItems; i++) { const CItemEx &item = *m_Items[allFilesMode ? i : indices[i]]; totalUnPacked += item.UnPackSize; totalPacked += item.PackSize; } RINOK(extractCallback->SetTotal(totalUnPacked)); quint64 currentTotalUnPacked = 0, currentTotalPacked = 0; quint64 currentItemUnPacked, currentItemPacked; for (i = 0; i < numItems; i++, currentTotalUnPacked += currentItemUnPacked, currentTotalPacked += currentItemPacked) { currentItemUnPacked = 0; currentItemPacked = 0; qint32 askMode = testMode ? NArchive::NExtract::NAskMode::kTest : NArchive::NExtract::NAskMode::kExtract; qint32 index = allFilesMode ? i : indices[i]; ISequentialOutStream *prealOutStream; RINOK(extractCallback->GetStream(index, &prealOutStream, askMode)); RefPtr<ISequentialOutStream> realOutStream(prealOutStream); CItemEx item = *m_Items[index]; if (!item.FromLocal) { HRESULT res = m_Archive.ReadLocalItemAfterCdItem(item); if (res == S_FALSE) { if (item.IsDirectory() || realOutStream || testMode) { RINOK(extractCallback->PrepareOperation(askMode)); realOutStream = 0; RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kUnSupportedMethod)); } continue; } RINOK(res); } if (item.IsDirectory() || item.IgnoreItem()) { // if (!testMode) { RINOK(extractCallback->PrepareOperation(askMode)); RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); } continue; } currentItemUnPacked = item.UnPackSize; currentItemPacked = item.PackSize; if (!testMode && (!realOutStream)) continue; RINOK(extractCallback->PrepareOperation(askMode)); qint32 res; RINOK(myDecoder.Decode( m_Archive, item, realOutStream, extractCallback, _numThreads, res)); RINOK(extractCallback->SetOperationResult(res)) } return S_OK; }