Esempio n. 1
0
static HRESULT UnpackData(IInStream *inStream, const CResource &resource, bool lzxMode, CByteBuffer &buf, Byte *digest)
{
  size_t size = (size_t)resource.UnpackSize;
  if (size != resource.UnpackSize)
    return E_OUTOFMEMORY;
  buf.Free();
  buf.SetCapacity(size);

  CSequentialOutStreamImp2 *outStreamSpec = new CSequentialOutStreamImp2();
  CMyComPtr<ISequentialOutStream> outStream = outStreamSpec;
  outStreamSpec->Init((Byte *)buf, size);

  CUnpacker unpacker;
  return unpacker.Unpack(inStream, resource, lzxMode, outStream, NULL, digest);
}
Esempio n. 2
0
STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
    Int32 testMode, IArchiveExtractCallback *extractCallback)
{
  COM_TRY_BEGIN
  bool allFilesMode = (numItems == (UInt32)(Int32)-1);

  if (allFilesMode)
    numItems = _db.SortedItems.Size() + _numXmlItems + _db.VirtualRoots.Size() + _numIgnoreItems;
  if (numItems == 0)
    return S_OK;

  UInt32 i;
  UInt64 totalSize = 0;
  for (i = 0; i < numItems; i++)
  {
    UInt32 index = allFilesMode ? i : indices[i];
    if (index < _db.SortedItems.Size())
    {
      int streamIndex = _db.Items[_db.SortedItems[index]].StreamIndex;
      if (streamIndex >= 0)
      {
        const CStreamInfo &si = _db.DataStreams[streamIndex];
        totalSize += si.Resource.UnpackSize;
      }
    }
    else
    {
      index -= _db.SortedItems.Size();
      if (index < (UInt32)_numXmlItems)
        totalSize += _xmls[index].Data.Size();
    }
  }

  RINOK(extractCallback->SetTotal(totalSize));

  UInt64 currentTotalPacked = 0;
  UInt64 currentTotalUnPacked = 0;
  UInt64 currentItemUnPacked, currentItemPacked;

  int prevSuccessStreamIndex = -1;

  CUnpacker unpacker;

  CLocalProgress *lps = new CLocalProgress;
  CMyComPtr<ICompressProgressInfo> progress = lps;
  lps->Init(extractCallback, false);

  for (i = 0; i < numItems; currentTotalUnPacked += currentItemUnPacked,
      currentTotalPacked += currentItemPacked)
  {
    currentItemUnPacked = 0;
    currentItemPacked = 0;

    lps->InSize = currentTotalPacked;
    lps->OutSize = currentTotalUnPacked;

    RINOK(lps->SetCur());
    UInt32 index = allFilesMode ? i : indices[i];
    i++;
    Int32 askMode = testMode ?
        NExtract::NAskMode::kTest :
        NExtract::NAskMode::kExtract;

    CMyComPtr<ISequentialOutStream> realOutStream;
    RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
    if (index >= _db.SortedItems.Size())
    {
      if (!testMode && !realOutStream)
        continue;
      RINOK(extractCallback->PrepareOperation(askMode));
      index -= _db.SortedItems.Size();
      if (index < (UInt32)_numXmlItems)
      {
        const CByteBuffer &data = _xmls[index].Data;
        currentItemUnPacked = data.Size();
        if (realOutStream)
        {
          RINOK(WriteStream(realOutStream, (const Byte *)data, data.Size()));
          realOutStream.Release();
        }
      }
      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
      continue;
    }

    const CItem &item = _db.Items[_db.SortedItems[index]];
    int streamIndex = item.StreamIndex;
    if (streamIndex < 0)
    {
      if (!testMode && !realOutStream)
        continue;
      RINOK(extractCallback->PrepareOperation(askMode));
      realOutStream.Release();
      RINOK(extractCallback->SetOperationResult(_db.ItemHasStream(item) ?
          NExtract::NOperationResult::kDataError :
          NExtract::NOperationResult::kOK));
      continue;
    }

    const CStreamInfo &si = _db.DataStreams[streamIndex];
    currentItemUnPacked = si.Resource.UnpackSize;
    currentItemPacked = si.Resource.PackSize;

    if (!testMode && !realOutStream)
      continue;
    RINOK(extractCallback->PrepareOperation(askMode));
    Int32 opRes = NExtract::NOperationResult::kOK;
    if (streamIndex != prevSuccessStreamIndex || realOutStream)
    {
      Byte digest[kHashSize];
      const CVolume &vol = _volumes[si.PartNumber];
      HRESULT res = unpacker.Unpack(vol.Stream, si.Resource, vol.Header.IsLzxMode(),
          realOutStream, progress, digest);
      if (res == S_OK)
      {
        if (memcmp(digest, si.Hash, kHashSize) == 0)
          prevSuccessStreamIndex = streamIndex;
        else
          opRes = NExtract::NOperationResult::kCRCError;
      }
      else if (res == S_FALSE)
        opRes = NExtract::NOperationResult::kDataError;
      else
        return res;
    }
    realOutStream.Release();
    RINOK(extractCallback->SetOperationResult(opRes));
  }
  return S_OK;
  COM_TRY_END
}