// NOTE: this function is not a method of BitMemExtractor because it would dirty the header with extra dependencies CMyComPtr< IInArchive > openArchive( const Bit7zLibrary& lib, const BitInFormat& format, const vector< byte_t >& in_buffer, const BitArchiveOpener& opener ) { CMyComPtr< IInArchive > inArchive; const GUID formatGUID = format.guid(); lib.createArchiveObject( &formatGUID, &::IID_IInArchive, reinterpret_cast< void** >( &inArchive ) ); CBufInStream* bufStreamSpec = new CBufInStream; CMyComPtr< IInStream > bufStream( bufStreamSpec ); bufStreamSpec->Init( &in_buffer[0], in_buffer.size() ); OpenCallback* openCallbackSpec = new OpenCallback( opener ); CMyComPtr< IArchiveOpenCallback > openCallback( openCallbackSpec ); if ( inArchive->Open( bufStream, 0, openCallback ) != S_OK ) { throw BitException( L"Cannot open archive buffer" ); } return inArchive; }
STDMETHODIMP CArchiveUpdateCallback::GetStream2(UInt32 index, ISequentialInStream **inStream, UInt32 mode) { COM_TRY_BEGIN *inStream = NULL; const CUpdatePair2 &up = (*UpdatePairs)[index]; if (!up.NewData) return E_FAIL; RINOK(Callback->CheckBreak()); // RINOK(Callback->Finalize()); bool isDir = IsDir(up); if (up.IsAnti) { UString name; if (up.ArcIndex >= 0) name = (*ArcItems)[up.ArcIndex].Name; else if (up.DirIndex >= 0) name = DirItems->GetLogPath(up.DirIndex); RINOK(Callback->GetStream(name, isDir, true, mode)); /* 9.33: fixed. Handlers expect real stream object for files, even for anti-file. so we return empty stream */ if (!isDir) { CBufInStream *inStreamSpec = new CBufInStream(); CMyComPtr<ISequentialInStream> inStreamLoc = inStreamSpec; inStreamSpec->Init(NULL, 0); *inStream = inStreamLoc.Detach(); } return S_OK; } RINOK(Callback->GetStream(DirItems->GetLogPath(up.DirIndex), isDir, false, mode)); if (isDir) return S_OK; if (StdInMode) { if (mode != NUpdateNotifyOp::kAdd && mode != NUpdateNotifyOp::kUpdate) return S_OK; CStdInFileStream *inStreamSpec = new CStdInFileStream; CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec); *inStream = inStreamLoc.Detach(); } else { CInFileStream *inStreamSpec = new CInFileStream; CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec); inStreamSpec->SupportHardLinks = StoreHardLinks; inStreamSpec->Callback = this; inStreamSpec->CallbackRef = index; const FString path = DirItems->GetPhyPath(up.DirIndex); _openFiles_Indexes.Add(index); _openFiles_Paths.Add(path); #if defined(_WIN32) && !defined(UNDER_CE) if (DirItems->Items[up.DirIndex].AreReparseData()) { if (!inStreamSpec->File.OpenReparse(path)) { return Callback->OpenFileError(path, ::GetLastError()); } } else #endif if (!inStreamSpec->OpenShared(path, ShareForWrite)) { DWORD error = ::GetLastError(); HRESULT hres = Callback->OpenFileError(path, error); if (StopAfterOpenError) if (hres == S_OK || hres == S_FALSE) return HRESULT_FROM_WIN32(error); return hres; } if (StoreHardLinks) { CStreamFileProps props; if (inStreamSpec->GetProps2(&props) == S_OK) { if (props.NumLinks > 1) { CKeyKeyValPair pair; pair.Key1 = props.VolID; pair.Key2 = props.FileID_Low; pair.Value = index; unsigned numItems = _map.Size(); unsigned pairIndex = _map.AddToUniqueSorted2(pair); if (numItems == _map.Size()) { // const CKeyKeyValPair &pair2 = _map.Pairs[pairIndex]; _hardIndex_From = index; _hardIndex_To = pairIndex; // we could return NULL as stream, but it's better to return real stream // return S_OK; } } } } if (ProcessedItemsStatuses) { #ifndef _7ZIP_ST NSynchronization::CCriticalSectionLock lock(CS); #endif ProcessedItemsStatuses[(unsigned)up.DirIndex] = 1; } *inStream = inStreamLoc.Detach(); } return S_OK; COM_TRY_END }