HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item) { filled = false; UInt32 processedSize; Byte startHeader[2]; RINOK(ReadBytes(startHeader, 2, processedSize)) if (processedSize == 0) return S_OK; if (processedSize == 1) return (startHeader[0] == 0) ? S_OK: S_FALSE; if (startHeader[0] == 0 && startHeader[1] == 0) return S_OK; Byte header[256]; const UInt32 kBasicPartSize = 22; RINOK(ReadBytes(header, kBasicPartSize, processedSize)); if (processedSize != kBasicPartSize) return (startHeader[0] == 0) ? S_OK: S_FALSE; const Byte *p = header; memmove(item.Method, p, kMethodIdSize); if (!item.IsValidMethod()) return S_OK; p += kMethodIdSize; p = ReadUInt32(p, item.PackSize); p = ReadUInt32(p, item.Size); p = ReadUInt32(p, item.ModifiedTime); item.Attributes = *p++; item.Level = *p++; if (item.Level > 2) return S_FALSE; UInt32 headerSize; if (item.Level < 2) { headerSize = startHeader[0]; if (headerSize < kBasicPartSize) return S_FALSE; UInt32 remain = headerSize - kBasicPartSize; RINOK(CheckReadBytes(header + kBasicPartSize, remain)); if (startHeader[1] != CalcSum(header, headerSize)) return S_FALSE; size_t nameLength = *p++; if ((p - header) + nameLength + 2 > headerSize) return S_FALSE; p = ReadString(p, nameLength, item.Name); } else headerSize = startHeader[0] | ((UInt32)startHeader[1] << 8); p = ReadUInt16(p, item.CRC); if (item.Level != 0) { if (item.Level == 2) { RINOK(CheckReadBytes(header + kBasicPartSize, 2)); } if ((size_t)(p - header) + 3 > headerSize) return S_FALSE; item.OsId = *p++; UInt16 nextSize; p = ReadUInt16(p, nextSize); while (nextSize != 0) { if (nextSize < 3) return S_FALSE; if (item.Level == 1) { if (item.PackSize < nextSize) return S_FALSE; item.PackSize -= nextSize; } CExtension ext; RINOK(CheckReadBytes(&ext.Type, 1)) nextSize -= 3; ext.Data.SetCapacity(nextSize); RINOK(CheckReadBytes((Byte *)ext.Data, nextSize)) item.Extensions.Add(ext); Byte hdr2[2]; RINOK(CheckReadBytes(hdr2, 2)); ReadUInt16(hdr2, nextSize); } } item.DataPosition = m_Position; filled = true; return S_OK; }