Exemple #1
0
        DotNetMultiFileResourcesImpl(HexBufferFile file, Bit7String?resourceTypeSpan, Bit7String?resourceSetTypeSpan, HexPosition versionPosition, HexSpan paddingSpan, Bit7String[] typeNames, int numResources, HexPosition dataSectionPosition, HexPosition nameSectionPosition)
            : base(file)
        {
            DataSectionPosition = dataSectionPosition;
            var headerSpan = new HexBufferSpan(file.Buffer, HexSpan.FromBounds(file.Span.Start, nameSectionPosition));

            Header = new DotNetMultiFileResourceHeaderDataImpl(headerSpan, resourceTypeSpan, resourceSetTypeSpan, versionPosition, paddingSpan, typeNames, numResources);
            ResourceInfo[] resourceInfos;
            dataArray = CreateDataArray(typeNames, numResources, paddingSpan.End, dataSectionPosition, nameSectionPosition, out resourceInfos);

            var files = new List <BufferFileOptions>(resourceInfos.Length);

            foreach (var info in resourceInfos)
            {
                var data = info.ResData;
                if (data == null)
                {
                    continue;
                }
                if (data.NestedFileData.IsEmpty)
                {
                    continue;
                }
                if (!IsNestedFile(data.TypeCode))
                {
                    continue;
                }
                var name         = Encoding.Unicode.GetString(File.Buffer.ReadBytes(info.UnicodeName.StringSpan));
                var filteredName = NameUtils.FilterName(name);
                var tags         = data.TypeCode >= ResourceTypeCode.UserTypes ? tagsSerialized : tagsNonSerialized;
                files.Add(new BufferFileOptions(data.NestedFileData, filteredName, string.Empty, tags));
            }
            if (files.Count > 0)
            {
                File.CreateFiles(files.ToArray());
            }
        }
        static DotNetMultiFileResourcesImpl?TryReadCore(HexBufferFile file)
        {
            if (file is null)
            {
                throw new ArgumentNullException(nameof(file));
            }
            if (file.Span.Length < 0x1C)
            {
                return(null);
            }
            var buffer = file.Buffer;
            var pos    = file.Span.Start;

            if (buffer.ReadUInt32(pos) != 0xBEEFCACE)
            {
                return(null);
            }

            int resMgrHeaderVersion = buffer.ReadInt32(pos + 4);
            int headerSize          = buffer.ReadInt32(pos + 8);

            if (resMgrHeaderVersion < 0 || headerSize < 0)
            {
                return(null);
            }
            pos += 0xC;

            Bit7String?resourceTypeSpan    = null;
            Bit7String?resourceSetTypeSpan = null;

            if (resMgrHeaderVersion > 1)
            {
                pos += headerSize;
            }
            else
            {
                resourceTypeSpan    = ReadBit7String(buffer, ref pos, file.Span.End);
                resourceSetTypeSpan = ReadBit7String(buffer, ref pos, file.Span.End);
                if (resourceTypeSpan is null || resourceSetTypeSpan is null)
                {
                    return(null);
                }
                var resourceType = Encoding.UTF8.GetString(buffer.ReadBytes(resourceTypeSpan.Value.StringSpan));
                if (!Regex.IsMatch(resourceType, @"^System\.Resources\.ResourceReader,\s*mscorlib,"))
                {
                    return(null);
                }
            }

            var versionPosition = pos;

            if (pos + 0x0C > file.Span.End)
            {
                return(null);
            }
            uint version = buffer.ReadUInt32(pos);

            if (version != 2)
            {
                return(null);               //TODO: Support version 1
            }
            int numResources = buffer.ReadInt32(pos + 4);
            int numTypes     = buffer.ReadInt32(pos + 8);

            if (numResources < 0 || numTypes < 0)
            {
                return(null);
            }
            pos += 0x0C;
            var typeNames = new Bit7String[numTypes];

            for (int i = 0; i < typeNames.Length; i++)
            {
                var info = ReadBit7String(buffer, ref pos, file.Span.End);
                if (info is null)
                {
                    return(null);
                }
                typeNames[i] = info.Value;
            }

            var paddingStart = pos;

            pos = file.AlignUp(pos, 8);
            var paddingSpan = HexSpan.FromBounds(paddingStart, pos);

            if (pos + (ulong)numResources * 8 + 4 > file.Span.End)
            {
                return(null);
            }
            pos += (ulong)numResources * 8;
            int dataSectionOffset = buffer.ReadInt32(pos);

            pos += 4;
            if (dataSectionOffset < 0 || dataSectionOffset < (pos - file.Span.Start))
            {
                return(null);
            }
            // Use > and not >= in case it's an empty resource
            if (dataSectionOffset > file.Span.Length)
            {
                return(null);
            }
            var dataSectionPosition = file.Span.Start + dataSectionOffset;
            var nameSectionPosition = pos;

            return(new DotNetMultiFileResourcesImpl(file, resourceTypeSpan, resourceSetTypeSpan, versionPosition, paddingSpan, typeNames, numResources, dataSectionPosition, nameSectionPosition));
        }
Exemple #3
0
        public DotNetMultiFileResourceHeaderDataImpl(HexBufferSpan span, Bit7String?resourceTypeSpan, Bit7String?resourceSetTypeSpan, HexPosition versionPosition, HexSpan paddingSpan, Bit7String[] typeNames, int numResources)
            : base(span)
        {
            var buffer = span.Buffer;
            var pos    = span.Start.Position;

            MagicNum            = new StructField <UInt32Data>("MagicNum", new UInt32Data(buffer, pos));
            ResMgrHeaderVersion = new StructField <UInt32Data>("ResMgrHeaderVersion", new UInt32Data(buffer, pos + 4));
            HeaderSize          = new StructField <UInt32Data>("HeaderSize", new UInt32Data(buffer, pos + 8));

            if (resourceTypeSpan == null)
            {
                if (resourceSetTypeSpan != null)
                {
                    throw new ArgumentException();
                }
                UnknownHeader = new StructField <VirtualArrayData <ByteData> >("Header", ArrayData.CreateVirtualByteArray(new HexBufferSpan(buffer, HexSpan.FromBounds(pos + 0x0C, versionPosition))));
            }
            else
            {
                if (resourceSetTypeSpan == null)
                {
                    throw new ArgumentNullException(nameof(resourceSetTypeSpan));
                }
                ReaderType      = new StructField <Bit7EncodedStringData>("ReaderType", new Bit7EncodedStringData(buffer, resourceTypeSpan.Value.LengthSpan, resourceTypeSpan.Value.StringSpan, Encoding.UTF8));
                ResourceSetType = new StructField <Bit7EncodedStringData>("ResourceSetType", new Bit7EncodedStringData(buffer, resourceSetTypeSpan.Value.LengthSpan, resourceSetTypeSpan.Value.StringSpan, Encoding.UTF8));
            }

            pos          = versionPosition;
            Version      = new StructField <UInt32Data>("Version", new UInt32Data(buffer, pos));
            NumResources = new StructField <UInt32Data>("NumResources", new UInt32Data(buffer, pos + 4));
            NumTypes     = new StructField <UInt32Data>("NumTypes", new UInt32Data(buffer, pos + 8));
            pos         += 0x0C;

            var fields  = new ArrayField <Bit7EncodedStringData> [typeNames.Length];
            var currPos = pos;

            for (int i = 0; i < fields.Length; i++)
            {
                var info  = typeNames[i];
                var field = new ArrayField <Bit7EncodedStringData>(new Bit7EncodedStringData(buffer, info.LengthSpan, info.StringSpan, Encoding.UTF8), (uint)i);
                fields[i] = field;
                currPos   = field.Data.Span.End;
            }
            TypeNames = new StructField <VariableLengthArrayData <Bit7EncodedStringData> >("TypeNames", new VariableLengthArrayData <Bit7EncodedStringData>(string.Empty, new HexBufferSpan(buffer, HexSpan.FromBounds(pos, currPos)), fields));

            Alignment8 = new StructField <ArrayData <ByteData> >("Padding", ArrayData.CreateByteArray(buffer, paddingSpan.Start, (int)paddingSpan.Length.ToUInt64()));
            pos        = paddingSpan.End;

            NameHashes        = new StructField <VirtualArrayData <UInt32Data> >("NameHashes", ArrayData.CreateVirtualUInt32Array(new HexBufferSpan(buffer, new HexSpan(pos, (ulong)numResources * 4))));
            pos              += (ulong)numResources * 4;
            NamePositions     = new StructField <VirtualArrayData <UInt32Data> >("NamePositions", ArrayData.CreateVirtualUInt32Array(new HexBufferSpan(buffer, new HexSpan(pos, (ulong)numResources * 4))));
            pos              += (ulong)numResources * 4;
            DataSectionOffset = new StructField <FileOffsetData>("DataSectionOffset", new FileOffsetData(buffer, pos));
            pos              += 4;
            if (pos != span.Span.End)
            {
                throw new ArgumentOutOfRangeException(nameof(span));
            }

            var list = new List <BufferField>(13);

            list.Add(MagicNum);
            list.Add(ResMgrHeaderVersion);
            list.Add(HeaderSize);
            if (UnknownHeader != null)
            {
                list.Add(UnknownHeader);
            }
            if (ReaderType != null)
            {
                list.Add(ReaderType);
            }
            if (ResourceSetType != null)
            {
                list.Add(ResourceSetType);
            }
            list.Add(Version);
            list.Add(NumResources);
            list.Add(NumTypes);
            list.Add(TypeNames);
            list.Add(Alignment8);
            list.Add(NameHashes);
            list.Add(NamePositions);
            list.Add(DataSectionOffset);
            Fields = list.ToArray();
        }