예제 #1
0
 internal object ReadField(long dataOffset, Partition.FieldDefinitionEntry field)
 {
     lock (this._DataLock)
     {
         this._Data.Position = dataOffset + field.DataOffset;
         return(this.ReadData(field.TypeIndex, field.Flags));
     }
 }
예제 #2
0
        public void Deserialize(Stream input)
        {
            var basePosition = input.Position;

            var magic = input.ReadValueU32(Endian.Little);

            if (magic != Signature && magic.Swap() != Signature)
            {
                throw new FormatException();
            }
            var endian = magic == Signature ? Endian.Little : Endian.Big;

            var headerSize = input.ReadValueU32(endian);

            if (basePosition + headerSize > input.Length)
            {
                throw new EndOfStreamException();
            }

            var dataSize = input.ReadValueU32(endian);

            if (basePosition + headerSize + dataSize > input.Length)
            {
                throw new EndOfStreamException();
            }

            var importCount           = input.ReadValueU32(endian);
            var instanceCount         = input.ReadValueU16(endian);
            var namedInstanceCount    = input.ReadValueU16(endian);
            var exportedInstanceCount = input.ReadValueU16(endian);
            var typeDefinitionCount   = input.ReadValueU16(endian);
            var fieldDefinitionCount  = input.ReadValueU16(endian);
            var nameTableSize         = input.ReadValueU16(endian);
            var stringTableSize       = input.ReadValueU32(endian);
            var arrayCount            = input.ReadValueU32(endian);
            var arrayOffset           = input.ReadValueU32(endian);
            var guid = input.ReadValueGuid(endian);

            input.Seek(8, SeekOrigin.Current);

            var computedHeaderSize = 64 +
                                     (importCount * 32) +
                                     nameTableSize +
                                     (fieldDefinitionCount * 16) +
                                     (typeDefinitionCount * 16) +
                                     (instanceCount * 4).Align(16) +
                                     (arrayCount * 12).Align(16);

            if (computedHeaderSize != headerSize)
            {
                throw new FormatException();
            }

            var importEntries = new Partition.ImportEntry[importCount];

            for (int i = 0; i < importCount; i++)
            {
                importEntries[i] = Partition.ImportEntry.Read(input, endian);
            }

            var nameTableBytes = input.ReadBytes(nameTableSize);
            var names          = new List <string>();

            using (var data = new MemoryStream(nameTableBytes, false))
            {
                while (data.Position < data.Length)
                {
                    names.Add(data.ReadStringZ(Encoding.UTF8));
                }
            }

            // TODO(gibbed): do this better.
            var hashesToNames = names.Distinct().ToDictionary(Common.Hashing.DJB.Compute, s => s);

            var fieldDefinitionEntries = new Partition.FieldDefinitionEntry[fieldDefinitionCount];

            for (int i = 0; i < fieldDefinitionCount; i++)
            {
                var fieldDefinitionEntry =
                    fieldDefinitionEntries[i] = Partition.FieldDefinitionEntry.Read(input, endian);
                if (fieldDefinitionEntry.Flags.UnknownFlags2 != 0)
                {
                    throw new FormatException();
                }
                fieldDefinitionEntries[i].Name = hashesToNames[fieldDefinitionEntries[i].NameHash];
            }

            var typeDefinitionEntries = new Partition.TypeDefinitionEntry[typeDefinitionCount];

            for (int i = 0; i < typeDefinitionCount; i++)
            {
                var typeDefinitionEntry =
                    typeDefinitionEntries[i] = Partition.TypeDefinitionEntry.Read(input, endian);
                if (typeDefinitionEntry.Flags.UnknownFlags2 != 0)
                {
                    throw new FormatException();
                }
                typeDefinitionEntries[i].Name = hashesToNames[typeDefinitionEntries[i].NameHash];
            }

            var instancePadding = (instanceCount * 4).Padding(16);
            var instanceEntries = new Partition.InstanceEntry[instanceCount];

            for (int i = 0; i < instanceCount; i++)
            {
                instanceEntries[i] = Partition.InstanceEntry.Read(input, endian);
            }
            input.Seek(instancePadding, SeekOrigin.Current);

            var arrayPadding = (arrayCount * 12).Padding(16);
            var arrayEntries = new Partition.ArrayEntry[arrayCount];

            for (int i = 0; i < arrayCount; i++)
            {
                arrayEntries[i] = Partition.ArrayEntry.Read(input, endian);
            }
            input.Seek(arrayPadding, SeekOrigin.Current);

            if (basePosition + headerSize != input.Position)
            {
                throw new FormatException();
            }

            var dataBytes = input.ReadBytes(dataSize);

            this._ImportEntries.Clear();
            this._FieldDefinitionEntries.Clear();
            this._TypeDefinitionEntries.Clear();
            this._InstanceEntries.Clear();
            this._ArrayEntries.Clear();

            this._Endian = endian;
            this._Guid   = guid;
            this._ImportEntries.AddRange(importEntries);
            this._NameTableBytes = nameTableBytes;
            this._FieldDefinitionEntries.AddRange(fieldDefinitionEntries);
            this._TypeDefinitionEntries.AddRange(typeDefinitionEntries);
            this._InstanceEntries.AddRange(instanceEntries);
            this._ArrayEntries.AddRange(arrayEntries);
            this._NamedInstanceCount    = namedInstanceCount;
            this._ExportedInstanceCount = exportedInstanceCount;
            this._StringTableSize       = stringTableSize;
            this._ArrayOffset           = arrayOffset;
            this._DataBytes             = dataBytes;
        }