HRESULT CInArchive::Open2(IInStream *stream, const UInt64 *searchHeaderSizeLimit) { m_CryptoMode = false; RINOK(stream->Seek(0, STREAM_SEEK_SET, &m_StreamStartPosition)); m_Position = m_StreamStartPosition; UInt64 arcStartPos; RINOK(FindSignatureInStream(stream, NHeader::kMarker, NHeader::kMarkerSize, searchHeaderSizeLimit, arcStartPos)); m_Position = arcStartPos + NHeader::kMarkerSize; RINOK(stream->Seek(m_Position, STREAM_SEEK_SET, NULL)); Byte buf[NHeader::NArchive::kArchiveHeaderSize + 1]; RINOK(ReadStream_FALSE(stream, buf, NHeader::NArchive::kArchiveHeaderSize)); AddToSeekValue(NHeader::NArchive::kArchiveHeaderSize); UInt32 blockSize = Get16(buf + 5); _header.EncryptVersion = 0; _header.Flags = Get16(buf + 3); UInt32 headerSize = NHeader::NArchive::kArchiveHeaderSize; if (_header.IsThereEncryptVer()) { if (blockSize <= headerSize) return S_FALSE; RINOK(ReadStream_FALSE(stream, buf + NHeader::NArchive::kArchiveHeaderSize, 1)); AddToSeekValue(1); _header.EncryptVersion = buf[NHeader::NArchive::kArchiveHeaderSize]; headerSize += 1; } if (blockSize < headerSize || buf[2] != NHeader::NBlockType::kArchiveHeader || (UInt32)Get16(buf) != (CrcCalc(buf + 2, headerSize - 2) & 0xFFFF)) return S_FALSE; size_t commentSize = blockSize - headerSize; _comment.SetCapacity(commentSize); RINOK(ReadStream_FALSE(stream, _comment, commentSize)); AddToSeekValue(commentSize); m_Stream = stream; _header.StartPosition = arcStartPos; 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 &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; }