Пример #1
0
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;
}