Esempio n. 1
0
// 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;
}
Esempio n. 2
0
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
}