⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 7zhandler.cpp

📁 一个7ZIP的解压源码。比较详细。里面含有四种语言的实现代码。
💻 CPP
📖 第 1 页 / 共 2 页
字号:
      break;
    case kpidBlock:
      {
        CNum folderIndex = _database.FileIndexToFolderIndexMap[index2];
        if (folderIndex != kNumNoIndex)
          prop = (UInt32)folderIndex;
      }
      break;
    case kpidPackedSize0:
    case kpidPackedSize1:
    case kpidPackedSize2:
    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))
          {
            prop = _database.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0);
          }
          else
            prop = (UInt64)0;
        }
        else
          prop = (UInt64)0;
      }
      break;
    #endif
    case kpidIsAnti:
      prop = item.IsAnti;
      break;
  }
  prop.Detach(value);
  return S_OK;
  COM_TRY_END
}

#ifdef _7Z_VOL

static const wchar_t *kExt = L"7z";
static const wchar_t *kAfterPart = L".7z";

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

#endif

STDMETHODIMP 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);
    }
    for (;;)
    {
      CMyComPtr<IInStream> inStream;
      if (!_volumes.IsEmpty())
      {
        if (!openVolumeCallback)
          break;
        if(_volumes.Size() == 1)
        {
          UString baseName;
          {
            NCOM::CPropVariant prop;
            RINOK(openVolumeCallback->GetProperty(kpidName, &prop));
            if (prop.vt != VT_BSTR)
              break;
            baseName = prop.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(
      EXTERNAL_CODECS_VARS
      _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_VOL
STDMETHODIMP 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;
    if (coder.MethodID != k_Copy)
      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_ONLY

STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties)
{
  COM_TRY_BEGIN
  #ifdef COMPRESS_MT
  const UInt32 numProcessors = NSystem::GetNumberOfProcessors();
  _numThreads = numProcessors;
  #endif

  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)
      {
        #ifdef COMPRESS_MT
        RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads));
        #endif
        continue;
      }
      else
        return E_INVALIDARG;
    }
  }
  return S_OK;
  COM_TRY_END
}  

#endif
#endif

IMPL_ISetCompressCodecsInfo

}}

⌨️ 快捷键说明

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