7zhandler.cpp

来自「由7-zip提供的压缩、解压缩程序」· C++ 代码 · 共 758 行 · 第 1/2 页

CPP
758
字号
    case kpidPackedSize3:    case kpidPackedSize4:      {        CNum folderIndex = _database.FileIndexToFolderIndexMap[index2];        if (folderIndex != kNumNoIndex)        {          const CFolder &folderInfo = _database.Folders[folderIndex];          if (_database.FolderStartFileIndex[folderIndex] == (CNum)index2 &&              folderInfo.PackStreams.Size() > (int)(propID - kpidPackedSize0))          {            propVariant = _database.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0);          }          else            propVariant = UInt64(0);        }        else          propVariant = UInt64(0);      }      break;    #endif    case kpidIsAnti:      propVariant = item.IsAnti;      break;  }  propVariant.Detach(value);  return S_OK;  COM_TRY_END}static const wchar_t *kExt = L"7z";static const wchar_t *kAfterPart = L".7z";#ifdef _7Z_VOLclass CVolumeName{  bool _first;  UString _unchangedPart;  UString _changedPart;      UString _afterPart;    public:  bool InitName(const UString &name)  {    _first = true;    int dotPos = name.ReverseFind('.');    UString basePart = name;    if (dotPos >= 0)    {      UString ext = name.Mid(dotPos + 1);      if (ext.CompareNoCase(kExt)==0 ||         ext.CompareNoCase(L"EXE") == 0)      {        _afterPart = kAfterPart;        basePart = name.Left(dotPos);      }    }    int numLetters = 1;    bool splitStyle = false;    if (basePart.Right(numLetters) == L"1")    {      while (numLetters < basePart.Length())      {        if (basePart[basePart.Length() - numLetters - 1] != '0')          break;        numLetters++;      }    }    else       return false;    _unchangedPart = basePart.Left(basePart.Length() - numLetters);    _changedPart = basePart.Right(numLetters);    return true;  }  UString GetNextName()  {    UString newName;     // if (_newStyle || !_first)    {      int i;      int numLetters = _changedPart.Length();      for (i = numLetters - 1; i >= 0; i--)      {        wchar_t c = _changedPart[i];        if (c == L'9')        {          c = L'0';          newName = c + newName;          if (i == 0)            newName = UString(L'1') + newName;          continue;        }        c++;        newName = UString(c) + newName;        i--;        for (; i >= 0; i--)          newName = _changedPart[i] + newName;        break;      }      _changedPart = newName;    }    _first = false;    return _unchangedPart + _changedPart + _afterPart;  }};#endifSTDMETHODIMP CHandler::Open(IInStream *stream,    const UInt64 *maxCheckStartPosition,     IArchiveOpenCallback *openArchiveCallback){  COM_TRY_BEGIN  Close();  #ifndef _SFX  _fileInfoPopIDs.Clear();  #endif  try  {    CMyComPtr<IArchiveOpenCallback> openArchiveCallbackTemp = openArchiveCallback;    #ifdef _7Z_VOL    CVolumeName seqName;    CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;    #endif    #ifndef _NO_CRYPTO    CMyComPtr<ICryptoGetTextPassword> getTextPassword;    if (openArchiveCallback)    {      openArchiveCallbackTemp.QueryInterface(          IID_ICryptoGetTextPassword, &getTextPassword);    }    #endif    #ifdef _7Z_VOL    if (openArchiveCallback)    {      openArchiveCallbackTemp.QueryInterface(IID_IArchiveOpenVolumeCallback, &openVolumeCallback);    }    while(true)    {      CMyComPtr<IInStream> inStream;      if (!_volumes.IsEmpty())      {        if (!openVolumeCallback)          break;        if(_volumes.Size() == 1)        {          UString baseName;          {            NCOM::CPropVariant propVariant;            RINOK(openVolumeCallback->GetProperty(kpidName, &propVariant));            if (propVariant.vt != VT_BSTR)              break;            baseName = propVariant.bstrVal;          }          seqName.InitName(baseName);        }        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;      CInArchive archive;      RINOK(archive.Open(inStream, maxCheckStartPosition));      _volumes.Add(CVolume());      CVolume &volume = _volumes.Back();      CArchiveDatabaseEx &database = volume.Database;      volume.Stream = inStream;      volume.StartRef2Index = _refs.Size();      HRESULT result = archive.ReadDatabase(database          #ifndef _NO_CRYPTO          , getTextPassword          #endif          );      if (result != S_OK)      {        _volumes.Clear();        return result;      }      database.Fill();      for(int i = 0; i < database.Files.Size(); i++)      {        CRef refNew;        refNew.VolumeIndex = _volumes.Size() - 1;        refNew.ItemIndex = i;        _refs.Add(refNew);        /*        const CFileItem &file = database.Files[i];        int j;        */        /*        for (j = _refs.Size() - 1; j >= 0; j--)        {          CRef2 &ref2 = _refs[j];          const CRef &ref = ref2.Refs.Back();          const CVolume &volume2 = _volumes[ref.VolumeIndex];          const CArchiveDatabaseEx &database2 = volume2.Database;          const CFileItem &file2 = database2.Files[ref.ItemIndex];          if (file2.Name.CompareNoCase(file.Name) == 0)          {            if (!file.IsStartPosDefined)              continue;            if (file.StartPos != ref2.StartPos + ref2.UnPackSize)              continue;            ref2.Refs.Add(refNew);            break;          }        }        */        /*        j = -1;        if (j < 0)        {          CRef2 ref2New;          ref2New.Refs.Add(refNew);          j = _refs.Add(ref2New);        }        CRef2 &ref2 = _refs[j];        ref2.UnPackSize += file.UnPackSize;        ref2.PackSize += database.GetFilePackSize(i);        if (ref2.Refs.Size() == 1 && file.IsStartPosDefined)          ref2.StartPos = file.StartPos;        */      }      if (database.Files.Size() != 1)        break;      const CFileItem &file = database.Files.Front();      if (!file.IsStartPosDefined)        break;    }    #else    CInArchive archive;    RINOK(archive.Open(stream, maxCheckStartPosition));    HRESULT result = archive.ReadDatabase(_database      #ifndef _NO_CRYPTO      , getTextPassword      #endif      );    RINOK(result);    _database.Fill();    _inStream = stream;    #endif  }  catch(...)  {    Close();    return S_FALSE;  }  // _inStream = stream;  #ifndef _SFX  FillPopIDs();  #endif  return S_OK;  COM_TRY_END}STDMETHODIMP CHandler::Close(){  COM_TRY_BEGIN  #ifdef _7Z_VOL  _volumes.Clear();  _refs.Clear();  #else  _inStream.Release();  _database.Clear();  #endif  return S_OK;  COM_TRY_END}#ifdef _7Z_VOLSTDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream){  if (index != 0)    return E_INVALIDARG;  *stream = 0;  CMultiStream *streamSpec = new CMultiStream;  CMyComPtr<ISequentialInStream> streamTemp = streamSpec;    UInt64 pos = 0;  const UString *fileName;  for (int i = 0; i < _refs.Size(); i++)  {    const CRef &ref = _refs[i];    const CVolume &volume = _volumes[ref.VolumeIndex];    const CArchiveDatabaseEx &database = volume.Database;    const CFileItem &file = database.Files[ref.ItemIndex];    if (i == 0)      fileName = &file.Name;    else      if (fileName->Compare(file.Name) != 0)        return S_FALSE;    if (!file.IsStartPosDefined)      return S_FALSE;    if (file.StartPos != pos)      return S_FALSE;    CNum folderIndex = database.FileIndexToFolderIndexMap[ref.ItemIndex];    if (folderIndex == kNumNoIndex)    {      if (file.UnPackSize != 0)        return E_FAIL;      continue;    }    if (database.NumUnPackStreamsVector[folderIndex] != 1)      return S_FALSE;    const CFolder &folder = database.Folders[folderIndex];    if (folder.Coders.Size() != 1)      return S_FALSE;    const CCoderInfo &coder = folder.Coders.Front();    if (coder.NumInStreams != 1 || coder.NumOutStreams != 1)      return S_FALSE;    const CAltCoderInfo &altCoder = coder.AltCoders.Front();    if (altCoder.MethodID.IDSize != 1 || altCoder.MethodID.ID[0] != 0)      return S_FALSE;    pos += file.UnPackSize;    CMultiStream::CSubStreamInfo subStreamInfo;    subStreamInfo.Stream = volume.Stream;    subStreamInfo.Pos = database.GetFolderStreamPos(folderIndex, 0);    subStreamInfo.Size = file.UnPackSize;    streamSpec->Streams.Add(subStreamInfo);  }  streamSpec->Init();  *stream = streamTemp.Detach();  return S_OK;}#endif#ifdef __7Z_SET_PROPERTIES#ifdef EXTRACT_ONLYSTDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties){  COM_TRY_BEGIN  const UInt32 numProcessors = NSystem::GetNumberOfProcessors();  _numThreads = numProcessors;  for (int i = 0; i < numProperties; i++)  {    UString name = names[i];    name.MakeUpper();    if (name.IsEmpty())      return E_INVALIDARG;    const PROPVARIANT &value = values[i];    UInt32 number;    int index = ParseStringToUInt32(name, number);    if (index == 0)    {      if(name.Left(2).CompareNoCase(L"MT") == 0)      {        RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads));        continue;      }      else        return E_INVALIDARG;    }  }  return S_OK;  COM_TRY_END}  #endif#endif}}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?