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

📄 wimhandler.cpp

📁 7z一个高压缩比的压缩程序源代码,重要的是里面的算法值得学习
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// WimHandler.cpp

#include "StdAfx.h"

#include "Common/IntToString.h"
#include "Common/Defs.h"
#include "Common/ComTry.h"
#include "Common/StringToInt.h"
#include "Common/UTFConvert.h"

#include "Windows/PropVariant.h"

#include "../../Common/StreamUtils.h"
#include "../../Common/ProgressUtils.h"

#include "../../../../C/CpuArch.h"

#include "WimHandler.h"

#define Get16(p) GetUi16(p)
#define Get32(p) GetUi32(p)
#define Get64(p) GetUi64(p)

using namespace NWindows;

namespace NArchive {
namespace NWim {

#define WIM_DETAILS

STATPROPSTG kProps[] =
{
  { NULL, kpidPath, VT_BSTR},
  { NULL, kpidIsDir, VT_BOOL},
  { NULL, kpidSize, VT_UI8},
  { NULL, kpidPackSize, VT_UI8},
  { NULL, kpidAttrib, VT_UI4},
  { NULL, kpidMethod, VT_BSTR},
  { NULL, kpidMTime, VT_FILETIME},
  { NULL, kpidCTime, VT_FILETIME},
  { NULL, kpidATime, VT_FILETIME}
  
  #ifdef WIM_DETAILS
  , { NULL, kpidVolume, VT_UI4}
  , { NULL, kpidOffset, VT_UI8}
  , { NULL, kpidLinks, VT_UI4}
  #endif
};

STATPROPSTG kArcProps[] =
{
  { NULL, kpidSize, VT_UI8},
  { NULL, kpidPackSize, VT_UI8},
  { NULL, kpidMethod, VT_BSTR},
  { NULL, kpidCTime, VT_FILETIME},
  { NULL, kpidMTime, VT_FILETIME},
  { NULL, kpidComment, VT_FILETIME},
  { NULL, kpidIsVolume, VT_BOOL},
  { NULL, kpidVolume, VT_UI4},
  { NULL, kpidNumVolumes, VT_UI4}
};

static bool ParseNumber64(const AString &s, UInt64 &res)
{
  const char *end;
  if (s.Left(2) == "0x")
  {
    if (s.Length() == 2)
      return false;
    res = ConvertHexStringToUInt64((const char *)s + 2, &end);
  }
  else
  {
    if (s.IsEmpty())
      return false;
    res = ConvertStringToUInt64(s, &end);
  }
  return *end == 0;
}

static bool ParseNumber32(const AString &s, UInt32 &res)
{
  UInt64 res64;
  if (!ParseNumber64(s, res64) || res64 >= ((UInt64)1 << 32))
    return false;
  res = (UInt32)res64;
  return true;
}

void ParseTime(const CXmlItem &item, bool &defined, FILETIME &ft, const AString &s)
{
  defined = false;
  int cTimeIndex = item.FindSubTag(s);
  if (cTimeIndex >= 0)
  {
    const CXmlItem &timeItem = item.SubItems[cTimeIndex];
    UInt32 high = 0, low = 0;
    if (ParseNumber32(timeItem.GetSubStringForTag("HIGHPART"), high) &&
      ParseNumber32(timeItem.GetSubStringForTag("LOWPART"), low))
    {
      defined = true;
      ft.dwHighDateTime = high;
      ft.dwLowDateTime = low;
    }
  }
}

void CImageInfo::Parse(const CXmlItem &item)
{
  ParseTime(item, CTimeDefined, CTime, "CREATIONTIME");
  ParseTime(item, MTimeDefined, MTime, "LASTMODIFICATIONTIME");
  NameDefined = ConvertUTF8ToUnicode(item.GetSubStringForTag("NAME"), Name);
  // IndexDefined = ParseNumber32(item.GetPropertyValue("INDEX"), Index);
}

void CXml::Parse()
{
  size_t size = Data.GetCapacity();
  if (size < 2 || (size & 1) != 0 || (size > 1 << 24))
    return;
  const Byte *p = Data;
  if (Get16(p) != 0xFEFF)
    return;
  UString s;
  {
    wchar_t *chars = s.GetBuffer((int)size / 2 + 1);
    for (size_t i = 2; i < size; i += 2)
      *chars++ = (wchar_t)Get16(p + i);
    *chars = 0;
    s.ReleaseBuffer();
  }

  AString utf;
  if (!ConvertUnicodeToUTF8(s, utf))
    return;
  ::CXml xml;
  if (!xml.Parse(utf))
    return;
  if (xml.Root.Name != "WIM")
    return;

  for (int i = 0; i < xml.Root.SubItems.Size(); i++)
  {
    const CXmlItem &item = xml.Root.SubItems[i];
    if (item.IsTagged("IMAGE"))
    {
      CImageInfo imageInfo;
      imageInfo.Parse(item);
      Images.Add(imageInfo);
    }
  }
}

static const wchar_t *kStreamsNamePrefix = L"Files" WSTRING_PATH_SEPARATOR;
static const wchar_t *kMethodLZX = L"LZX";
static const wchar_t *kMethodXpress = L"XPress";
static const wchar_t *kMethodCopy = L"Copy";

IMP_IInArchive_Props
IMP_IInArchive_ArcProps

STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{
  COM_TRY_BEGIN
  NWindows::NCOM::CPropVariant prop;

  const CImageInfo *image = NULL;
  if (m_Xmls.Size() == 1)
  {
    const CXml &xml = m_Xmls[0];
    if (xml.Images.Size() == 1)
      image = &xml.Images[0];
  }

  switch(propID)
  {
    case kpidSize: prop = m_Database.GetUnpackSize(); break;
    case kpidPackSize: prop = m_Database.GetPackSize(); break;
    
    case kpidCTime:
      if (m_Xmls.Size() == 1)
      {
        const CXml &xml = m_Xmls[0];
        int index = -1;
        for (int i = 0; i < xml.Images.Size(); i++)
        {
          const CImageInfo &image = xml.Images[i];
          if (image.CTimeDefined)
            if (index < 0 || ::CompareFileTime(&image.CTime, &xml.Images[index].CTime) < 0)
              index = i;
        }
        if (index >= 0)
          prop = xml.Images[index].CTime;
      }
      break;

    case kpidMTime:
      if (m_Xmls.Size() == 1)
      {
        const CXml &xml = m_Xmls[0];
        int index = -1;
        for (int i = 0; i < xml.Images.Size(); i++)
        {
          const CImageInfo &image = xml.Images[i];
          if (image.MTimeDefined)
            if (index < 0 || ::CompareFileTime(&image.MTime, &xml.Images[index].MTime) > 0)
              index = i;
        }
        if (index >= 0)
          prop = xml.Images[index].MTime;
      }
      break;

    case kpidComment: if (image != NULL && image->NameDefined) prop = image->Name; break;

    case kpidIsVolume:
      if (m_Xmls.Size() > 0)
      {
        UInt16 volIndex = m_Xmls[0].VolIndex;
        if (volIndex < m_Volumes.Size())
          prop = (m_Volumes[volIndex].Header.NumParts > 1);
      }
      break;
    case kpidVolume:
      if (m_Xmls.Size() > 0)
      {
        UInt16 volIndex = m_Xmls[0].VolIndex;
        if (volIndex < m_Volumes.Size())
          prop = (UInt32)m_Volumes[volIndex].Header.PartNumber;
      }
      break;
    case kpidNumVolumes: if (m_Volumes.Size() > 0) prop = (UInt32)(m_Volumes.Size() - 1); break;
    case kpidMethod:
    {
      bool lzx = false, xpress = false, copy = false;
      for (int i = 0; i < m_Xmls.Size(); i++)
      {
        const CVolume &vol = m_Volumes[m_Xmls[i].VolIndex];
        const CHeader &header = vol.Header;
        if (header.IsCompressed())
          if (header.IsLzxMode())
            lzx = true;
          else
            xpress = true;
        else
          copy = true;
      }
      UString res;
      if (lzx)
        res = kMethodLZX;
      if (xpress)
      {
        if (!res.IsEmpty())
          res += L' ';
        res += kMethodXpress;
      }
      if (copy)
      {
        if (!res.IsEmpty())
          res += L' ';
        res += kMethodCopy;
      }
      prop = res;
    }
  }
  prop.Detach(value);
  return S_OK;
  COM_TRY_END
}

STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
{
  COM_TRY_BEGIN
  NWindows::NCOM::CPropVariant prop;
  if (index < (UInt32)m_Database.Items.Size())
  {
    const CItem &item = m_Database.Items[index];
    const CStreamInfo *si = NULL;
    const CVolume *vol = NULL;
    if (item.StreamIndex >= 0)
    {
      si = &m_Database.Streams[item.StreamIndex];
      vol = &m_Volumes[si->PartNumber];
    }

    switch(propID)
    {
      case kpidPath:
        if (item.HasMetadata)
          prop = item.Name;
        else
        {
          wchar_t sz[32];
          ConvertUInt64ToString(item.StreamIndex, sz);
          UString s = sz;
          while (s.Length() < m_NameLenForStreams)
            s = L'0' + s;
          s = UString(kStreamsNamePrefix) + s;
          prop = s;
          break;
        }
        break;
      case kpidIsDir: prop = item.isDir(); break;
      case kpidAttrib: if (item.HasMetadata) prop = item.Attrib; break;
      case kpidCTime: if (item.HasMetadata) prop = item.CTime; break;
      case kpidATime: if (item.HasMetadata) prop = item.ATime; break;
      case kpidMTime: if (item.HasMetadata) prop = item.MTime; break;
      case kpidPackSize: prop = si ? si->Resource.PackSize : (UInt64)0; break;
      case kpidSize: prop = si ? si->Resource.UnpackSize : (UInt64)0; break;
      case kpidMethod: if (si) prop = si->Resource.IsCompressed() ?

⌨️ 快捷键说明

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