Exemple #1
0
HRESULT CHandler::Open2(IInStream *stream,
    const UInt64 *maxCheckStartPosition,
    IArchiveOpenCallback *openCallback)
{
  {
    CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;
    CMyComPtr<ICryptoGetTextPassword> getTextPassword;
    CMyComPtr<IArchiveOpenCallback> openArchiveCallbackWrap = openCallback;
    
    CVolumeName seqName;

    UInt64 totalBytes = 0;
    UInt64 curBytes = 0;

    if (openCallback)
    {
      openArchiveCallbackWrap.QueryInterface(IID_IArchiveOpenVolumeCallback, &openVolumeCallback);
      openArchiveCallbackWrap.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);
    }

    for (;;)
    {
      CMyComPtr<IInStream> inStream;
      if (!_archives.IsEmpty())
      {
        if (!openVolumeCallback)
          break;
        
        if (_archives.Size() == 1)
        {
          if (!_archiveInfo.IsVolume())
            break;
          UString baseName;
          {
            NCOM::CPropVariant prop;
            RINOK(openVolumeCallback->GetProperty(kpidName, &prop));
            if (prop.vt != VT_BSTR)
              break;
            baseName = prop.bstrVal;
          }
          seqName.InitName(baseName, _archiveInfo.HaveNewVolumeName());
        }

        UString fullName = seqName.GetNextName();
        HRESULT result = openVolumeCallback->GetStream(fullName, &inStream);
        if (result == S_FALSE)
          break;
        if (result != S_OK)
          return result;
        if (!stream)
          break;
      }
      else
        inStream = stream;

      UInt64 endPos = 0;
      RINOK(stream->Seek(0, STREAM_SEEK_END, &endPos));
      RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));
      if (openCallback)
      {
        totalBytes += endPos;
        RINOK(openCallback->SetTotal(NULL, &totalBytes));
      }
      
      NArchive::NRar::CInArchive archive;
      RINOK(archive.Open(inStream, maxCheckStartPosition));

      if (_archives.IsEmpty())
        archive.GetArchiveInfo(_archiveInfo);
     
      CItemEx item;
      for (;;)
      {
        if (archive.m_Position > endPos)
        {
          AddErrorMessage("Unexpected end of archive");
          break;
        }
        bool decryptionError;
        AString errorMessageLoc;
        HRESULT result = archive.GetNextItem(item, getTextPassword, decryptionError, errorMessageLoc);
        if (errorMessageLoc)
          AddErrorMessage(errorMessageLoc);
        if (result == S_FALSE)
        {
          if (decryptionError && _items.IsEmpty())
            return S_FALSE;
          break;
        }
        RINOK(result);
        if (item.IgnoreItem())
          continue;

        bool needAdd = true;
        if (item.IsSplitBefore())
        {
          if (!_refItems.IsEmpty())
          {
            CRefItem &refItem = _refItems.Back();
            refItem.NumItems++;
            needAdd = false;
          }
        }
        if (needAdd)
        {
          CRefItem refItem;
          refItem.ItemIndex = _items.Size();
          refItem.NumItems = 1;
          refItem.VolumeIndex = _archives.Size();
          _refItems.Add(refItem);
        }
        _items.Add(item);
        if (openCallback && _items.Size() % 100 == 0)
        {
          UInt64 numFiles = _items.Size();
          UInt64 numBytes = curBytes + item.Position;
          RINOK(openCallback->SetCompleted(&numFiles, &numBytes));
        }
      }
      curBytes += endPos;
      _archives.Add(archive);
    }
  }
  return S_OK;
}
Exemple #2
0
STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *callback)
{
  COM_TRY_BEGIN

  Close();
  {
    CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;

    CVolumeName seqName;
    if (callback)
      callback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback);

    UInt32 numVolumes = 1;

    for (UInt32 i = 1; i <= numVolumes; i++)
    {
      CMyComPtr<IInStream> curStream;
      if (i == 1)
        curStream = inStream;
      else
      {
        UString fullName = seqName.GetNextName(i);
        HRESULT result = openVolumeCallback->GetStream(fullName, &curStream);
        if (result == S_FALSE)
          continue;
        if (result != S_OK)
          return result;
        if (!curStream)
          break;
      }
      CHeader header;
      HRESULT res = NWim::ReadHeader(curStream, header, _phySize);
      if (res != S_OK)
      {
        if (i != 1 && res == S_FALSE)
          continue;
        return res;
      }
      _isArc = true;
      _bootIndex = header.BootIndex;
      _version = header.Version;
      _isOldVersion = header.IsOldVersion();
      if (_firstVolumeIndex >= 0)
        if (!header.AreFromOnArchive(_volumes[_firstVolumeIndex].Header))
          break;
      if (_volumes.Size() > header.PartNumber && _volumes[header.PartNumber].Stream)
        break;
      CWimXml xml;
      xml.VolIndex = header.PartNumber;
      res = _db.OpenXml(curStream, header, xml.Data);
      if (res == S_OK)
      {
        if (!xml.Parse())
          _xmlError = true;

        UInt64 totalFiles = xml.GetTotalFilesAndDirs() + xml.Images.Size();
        totalFiles += 16 + xml.Images.Size() * 4; // we reserve some additional items
        if (totalFiles >= ((UInt32)1 << 30))
          totalFiles = 0;
        res = _db.Open(curStream, header, (unsigned)totalFiles, callback);
      }
      if (res != S_OK)
      {
        if (i != 1 && res == S_FALSE)
          continue;
        return res;
      }

      while (_volumes.Size() <= header.PartNumber)
        _volumes.AddNew();
      CVolume &volume = _volumes[header.PartNumber];
      volume.Header = header;
      volume.Stream = curStream;

      _firstVolumeIndex = header.PartNumber;

      if (_xmls.IsEmpty() || xml.Data != _xmls[0].Data)
      {
        wchar_t sz[16];
        ConvertUInt32ToString(xml.VolIndex, sz);
        xml.FileName = L'[';
        xml.FileName += sz;
        xml.FileName += L"].xml";
        _xmls.Add(xml);
      }

      if (i == 1)
      {
        if (header.PartNumber != 1)
          break;
        if (!openVolumeCallback)
          break;
        numVolumes = header.NumParts;
        {
          NCOM::CPropVariant prop;
          RINOK(openVolumeCallback->GetProperty(kpidName, &prop));
          if (prop.vt != VT_BSTR)
            break;
          seqName.InitName(prop.bstrVal);
        }
      }
    }

    RINOK(_db.FillAndCheck());
    int defaultImageIndex = (int)_defaultImageNumber - 1;

    bool showImageNumber = (_db.Images.Size() != 1 && defaultImageIndex < 0);
    if (!showImageNumber && _set_use_ShowImageNumber)
      showImageNumber = _set_showImageNumber;

    if (!showImageNumber && _keepMode_ShowImageNumber)
      showImageNumber = true;

    _showImageNumber = showImageNumber;

    RINOK(_db.GenerateSortedItems(defaultImageIndex, showImageNumber));
    RINOK(_db.ExtractReparseStreams(_volumes, callback));

    /*
    wchar_t sz[16];
    ConvertUInt32ToString(_db.DataStreams.Size(), sz);
    _nameLenForStreams = MyStringLen(sz);
    */

    _xmlInComments = !_showImageNumber;
    _numXmlItems = (_xmlInComments ? 0 : _xmls.Size());
    _numIgnoreItems = _db.ThereAreDeletedStreams ? 1 : 0;
  }
  return S_OK;
  COM_TRY_END
}
Exemple #3
0
STDMETHODIMP CHandler::Open(IInStream *inStream,
    const UInt64 * /* maxCheckStartPosition */,
    IArchiveOpenCallback *openArchiveCallback)
{
  COM_TRY_BEGIN
  Close();
  try
  {
    CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;
    
    CVolumeName seqName;
    if (openArchiveCallback != NULL)
      openArchiveCallback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback);

    UInt32 numVolumes = 1;
    int firstVolumeIndex = -1;
    for (UInt32 i = 1; i <= numVolumes; i++)
    {
      CMyComPtr<IInStream> curStream;
      if (i != 1)
      {
        UString fullName = seqName.GetNextName(i);
        HRESULT result = openVolumeCallback->GetStream(fullName, &curStream);
        if (result == S_FALSE)
          continue;
        if (result != S_OK)
          return result;
        if (!curStream)
          break;
      }
      else
        curStream = inStream;
      CHeader header;
      HRESULT res = NWim::ReadHeader(curStream, header);
      if (res != S_OK)
      {
        if (i == 1)
          return res;
        if (res == S_FALSE)
          continue;
        return res;
      }
      if (firstVolumeIndex >= 0)
        if (!header.AreFromOnArchive(m_Volumes[firstVolumeIndex].Header))
          break;
      if (m_Volumes.Size() > header.PartNumber && m_Volumes[header.PartNumber].Stream)
        break;
      CXml xml;
      xml.VolIndex = header.PartNumber;
      res = OpenArchive(curStream, header, xml.Data, m_Database);
      if (res != S_OK)
      {
        if (i == 1)
          return res;
        if (res == S_FALSE)
          continue;
        return res;
      }
      
      while (m_Volumes.Size() <= header.PartNumber)
        m_Volumes.Add(CVolume());
      CVolume &volume = m_Volumes[header.PartNumber];
      volume.Header = header;
      volume.Stream = curStream;
      
      firstVolumeIndex = header.PartNumber;
      
      bool needAddXml = true;
      if (m_Xmls.Size() != 0)
        if (xml.Data == m_Xmls[0].Data)
          needAddXml = false;
      if (needAddXml)
      {
        xml.Parse();
        m_Xmls.Add(xml);
      }
      
      if (i == 1)
      {
        if (header.PartNumber != 1)
          break;
        if (!openVolumeCallback)
          break;
        numVolumes = header.NumParts;
        {
          NCOM::CPropVariant prop;
          RINOK(openVolumeCallback->GetProperty(kpidName, &prop));
          if (prop.vt != VT_BSTR)
            break;
          seqName.InitName(prop.bstrVal);
        }
      }
    }

    RINOK(SortDatabase(m_Database));

    wchar_t sz[32];
    ConvertUInt64ToString(m_Database.Streams.Size(), sz);
    m_NameLenForStreams = MyStringLen(sz);
  }
  catch(...)
  {
    return S_FALSE;
  }
  return S_OK;
  COM_TRY_END
}