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