示例#1
0
文件: CabIn.cpp 项目: bks/qz7
HRESULT CInArchive::Open2(IInStream *stream,
    const UInt64 *searchHeaderSizeLimit,
    CDatabase &database)
{
  database.Clear();
  RINOK(stream->Seek(0, STREAM_SEEK_SET, &database.StartPosition));

  RINOK(FindSignatureInStream(stream, NHeader::kMarker, NHeader::kMarkerSize,
      searchHeaderSizeLimit, database.StartPosition));

  RINOK(stream->Seek(database.StartPosition + NHeader::kMarkerSize, STREAM_SEEK_SET, NULL));
  if (!inBuffer.Create(1 << 17))
    return E_OUTOFMEMORY;
  inBuffer.SetStream(stream);
  inBuffer.Init();

  CInArchiveInfo &archiveInfo = database.ArchiveInfo;

  archiveInfo.Size = ReadUInt32(); // size of this cabinet file in bytes
  if (ReadUInt32() != 0)
    return S_FALSE;
  archiveInfo.FileHeadersOffset = ReadUInt32(); // offset of the first CFFILE entry
  if (ReadUInt32() != 0)
    return S_FALSE;

  archiveInfo.VersionMinor = ReadByte(); // cabinet file format version, minor
  archiveInfo.VersionMajor = ReadByte(); // cabinet file format version, major
  archiveInfo.NumFolders = ReadUInt16(); // number of CFFOLDER entries in this cabinet
  archiveInfo.NumFiles  = ReadUInt16(); // number of CFFILE entries in this cabinet
  archiveInfo.Flags = ReadUInt16();
  if (archiveInfo.Flags > 7)
    return S_FALSE;
  archiveInfo.SetID = ReadUInt16(); // must be the same for all cabinets in a set
  archiveInfo.CabinetNumber = ReadUInt16(); // number of this cabinet file in a set

  if (archiveInfo.ReserveBlockPresent())
  {
    archiveInfo.PerCabinetAreaSize = ReadUInt16(); // (optional) size of per-cabinet reserved area
    archiveInfo.PerFolderAreaSize = ReadByte(); // (optional) size of per-folder reserved area
    archiveInfo.PerDataBlockAreaSize = ReadByte(); // (optional) size of per-datablock reserved area

    Skeep(archiveInfo.PerCabinetAreaSize);
  }

  {
    if (archiveInfo.IsTherePrev())
      ReadOtherArchive(archiveInfo.PreviousArchive);
    if (archiveInfo.IsThereNext())
      ReadOtherArchive(archiveInfo.NextArchive);
  }
  
  int i;
  for(i = 0; i < archiveInfo.NumFolders; i++)
  {
    CFolder folder;

    folder.DataStart = ReadUInt32();
    folder.NumDataBlocks = ReadUInt16();
    folder.CompressionTypeMajor = ReadByte();
    folder.CompressionTypeMinor = ReadByte();

    Skeep(archiveInfo.PerFolderAreaSize);
    database.Folders.Add(folder);
  }
  
  RINOK(stream->Seek(database.StartPosition + archiveInfo.FileHeadersOffset, STREAM_SEEK_SET, NULL));

  inBuffer.SetStream(stream);
  inBuffer.Init();
  for(i = 0; i < archiveInfo.NumFiles; i++)
  {
    CItem item;
    item.Size = ReadUInt32();
    item.Offset = ReadUInt32();
    item.FolderIndex = ReadUInt16();
    UInt16 pureDate = ReadUInt16();
    UInt16 pureTime = ReadUInt16();
    item.Time = ((UInt32(pureDate) << 16)) | pureTime;
    item.Attributes = ReadUInt16();
    item.Name = SafeReadName();
    int folderIndex = item.GetFolderIndex(database.Folders.Size());
    if (folderIndex >= database.Folders.Size())
      return S_FALSE;
    database.Items.Add(item);
  }
  return S_OK;
}
HRESULT CInArchive::Open2(IInStream *stream,
    const UInt64 *searchHeaderSizeLimit,
    CDatabase &database)
{
  database.Clear();
  RINOK(stream->Seek(0, STREAM_SEEK_SET, &database.StartPosition));

  RINOK(FindSignatureInStream(stream, NHeader::kMarker, NHeader::kMarkerSize,
      searchHeaderSizeLimit, database.StartPosition));

  RINOK(stream->Seek(database.StartPosition + NHeader::kMarkerSize, STREAM_SEEK_SET, NULL));
  if (!inBuffer.Create(1 << 17))
    return E_OUTOFMEMORY;
  inBuffer.SetStream(stream);
  inBuffer.Init();

  CInArchiveInfo &ai = database.ArchiveInfo;

  ai.Size = ReadUInt32();
  if (ReadUInt32() != 0)
    return S_FALSE;
  ai.FileHeadersOffset = ReadUInt32();
  if (ReadUInt32() != 0)
    return S_FALSE;

  ai.VersionMinor = ReadByte();
  ai.VersionMajor = ReadByte();
  ai.NumFolders = ReadUInt16();
  ai.NumFiles = ReadUInt16();
  ai.Flags = ReadUInt16();
  if (ai.Flags > 7)
    return S_FALSE;
  ai.SetID = ReadUInt16();
  ai.CabinetNumber = ReadUInt16();

  if (ai.ReserveBlockPresent())
  {
    ai.PerCabinetAreaSize = ReadUInt16();
    ai.PerFolderAreaSize = ReadByte();
    ai.PerDataBlockAreaSize = ReadByte();

    Skip(ai.PerCabinetAreaSize);
  }

  {
    if (ai.IsTherePrev())
      ReadOtherArchive(ai.PreviousArchive);
    if (ai.IsThereNext())
      ReadOtherArchive(ai.NextArchive);
  }
  
  int i;
  for (i = 0; i < ai.NumFolders; i++)
  {
    CFolder folder;

    folder.DataStart = ReadUInt32();
    folder.NumDataBlocks = ReadUInt16();
    folder.CompressionTypeMajor = ReadByte();
    folder.CompressionTypeMinor = ReadByte();

    Skip(ai.PerFolderAreaSize);
    database.Folders.Add(folder);
  }
  
  RINOK(stream->Seek(database.StartPosition + ai.FileHeadersOffset, STREAM_SEEK_SET, NULL));

  inBuffer.SetStream(stream);
  inBuffer.Init();
  for (i = 0; i < ai.NumFiles; i++)
  {
    CItem item;
    item.Size = ReadUInt32();
    item.Offset = ReadUInt32();
    item.FolderIndex = ReadUInt16();
    UInt16 pureDate = ReadUInt16();
    UInt16 pureTime = ReadUInt16();
    item.Time = ((UInt32(pureDate) << 16)) | pureTime;
    item.Attributes = ReadUInt16();
    item.Name = SafeReadName();
    int folderIndex = item.GetFolderIndex(database.Folders.Size());
    if (folderIndex >= database.Folders.Size())
      return S_FALSE;
    database.Items.Add(item);
  }
  return S_OK;
}