public void ReadDatabase(CArchiveDatabaseEx db, IPasswordProvider pass) { db.Clear(); db.MajorVersion = _header[6]; db.MinorVersion = _header[7]; if (db.MajorVersion != 0) throw new InvalidDataException(); uint crcFromArchive = DataReader.Get32(_header, 8); long nextHeaderOffset = (long)DataReader.Get64(_header, 0xC); long nextHeaderSize = (long)DataReader.Get64(_header, 0x14); uint nextHeaderCrc = DataReader.Get32(_header, 0x1C); uint crc = CRC.kInitCRC; crc = CRC.Update(crc, nextHeaderOffset); crc = CRC.Update(crc, nextHeaderSize); crc = CRC.Update(crc, nextHeaderCrc); crc = CRC.Finish(crc); if (crc != crcFromArchive) throw new InvalidDataException(); db.StartPositionAfterHeader = _streamOrigin + 0x20; // empty header is ok if (nextHeaderSize == 0) return; if (nextHeaderOffset < 0 || nextHeaderSize < 0 || nextHeaderSize > Int32.MaxValue) throw new InvalidDataException(); if (nextHeaderOffset > _streamEnding - db.StartPositionAfterHeader) throw new InvalidDataException(); _stream.Seek(nextHeaderOffset, SeekOrigin.Current); byte[] header = new byte[nextHeaderSize]; _stream.ReadExact(header, 0, header.Length); if (CRC.Finish(CRC.Update(CRC.kInitCRC, header, 0, header.Length)) != nextHeaderCrc) throw new InvalidDataException(); using (CStreamSwitch streamSwitch = new CStreamSwitch()) { streamSwitch.Set(this, header); BlockType? type = ReadId(); if (type != BlockType.Header) { if (type != BlockType.EncodedHeader) throw new InvalidDataException(); var dataVector = ReadAndDecodePackedStreams(db.StartPositionAfterHeader, pass); // compressed header without content is odd but ok if (dataVector.Count == 0) return; if (dataVector.Count != 1) throw new InvalidDataException(); streamSwitch.Set(this, dataVector[0]); if (ReadId() != BlockType.Header) throw new InvalidDataException(); } ReadHeader(db, pass); } }