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; }
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 }
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 }