예제 #1
0
        public void WriteDefer(BamlDocument doc, int index, BinaryWriter wtr)
        {
            bool keys = true;

            do
            {
                switch (doc[index].Type)
                {
                case BamlRecordType.DefAttributeKeyString:
                case BamlRecordType.DefAttributeKeyType:
                case BamlRecordType.OptimizedStaticResource:
                    keys = true;
                    break;

                case BamlRecordType.StaticResourceStart:
                    NavigateTree(doc, BamlRecordType.StaticResourceStart, BamlRecordType.StaticResourceEnd, ref index);
                    keys = true;
                    break;

                case BamlRecordType.KeyElementStart:
                    NavigateTree(doc, BamlRecordType.KeyElementStart, BamlRecordType.KeyElementEnd, ref index);
                    keys = true;
                    break;

                default:
                    keys = false;
                    index--;
                    break;
                }
                index++;
            } while (keys);
            wtr.BaseStream.Seek(pos, SeekOrigin.Begin);
            wtr.Write((uint)(Record.Position - doc[index].Position));
        }
예제 #2
0
        public void ReadDefer(BamlDocument doc, int index, Func <long, BamlRecord> resolve)
        {
            bool keys = true;

            do
            {
                switch (doc[index].Type)
                {
                case BamlRecordType.DefAttributeKeyString:
                case BamlRecordType.DefAttributeKeyType:
                case BamlRecordType.OptimizedStaticResource:
                    keys = true;
                    break;

                case BamlRecordType.StaticResourceStart:
                    NavigateTree(doc, BamlRecordType.StaticResourceStart, BamlRecordType.StaticResourceEnd, ref index);
                    keys = true;
                    break;

                case BamlRecordType.KeyElementStart:
                    NavigateTree(doc, BamlRecordType.KeyElementStart, BamlRecordType.KeyElementEnd, ref index);
                    keys = true;
                    break;

                default:
                    keys = false;
                    index--;
                    break;
                }
                index++;
            } while (keys);
            Record = resolve(doc[index].Position + pos);
        }
예제 #3
0
        public static BamlElement Read(BamlDocument document)
        {
            Debug.Assert(document.Count > 0 && document[0].Type == BamlRecordType.DocumentStart);

            BamlElement current = null;
            var         stack   = new Stack <BamlElement>();

            for (int i = 0; i < document.Count; i++)
            {
                if (IsHeader(document[i]))
                {
                    BamlElement prev = current;

                    current          = new BamlElement();
                    current.Header   = document[i];
                    current.Body     = new List <BamlRecord>();
                    current.Children = new List <BamlElement>();

                    if (prev != null)
                    {
                        prev.Children.Add(current);
                        current.Parent = prev;
                        stack.Push(prev);
                    }
                }
                else if (IsFooter(document[i]))
                {
                    if (current == null)
                    {
                        throw new Exception("Unexpected footer.");
                    }

                    while (!IsMatch(current.Header, document[i]))
                    {
                        // End record can be omited (sometimes).
                        if (stack.Count > 0)
                        {
                            current = stack.Pop();
                        }
                    }
                    current.Footer = document[i];
                    if (stack.Count > 0)
                    {
                        current = stack.Pop();
                    }
                }
                else
                {
                    current.Body.Add(document[i]);
                }
            }
            Debug.Assert(stack.Count == 0);
            return(current);
        }
예제 #4
0
 static void NavigateTree(BamlDocument doc, BamlRecordType start, BamlRecordType end, ref int index)
 {
     index++;
     while (true)             //Assume there alway is a end
     {
         if (doc[index].Type == start)
         {
             NavigateTree(doc, start, end, ref index);
         }
         else if (doc[index].Type == end)
         {
             return;
         }
         index++;
     }
 }
예제 #5
0
            public XmlNsContext(BamlDocument doc, Dictionary <ushort, AssemblyDef> assemblyRefs)
            {
                this.doc = doc;

                this.assemblyRefs = new Dictionary <AssemblyDef, ushort>();
                foreach (var entry in assemblyRefs)
                {
                    this.assemblyRefs[entry.Value] = entry.Key;
                }

                for (int i = 0; i < doc.Count; i++)
                {
                    if (doc[i] is ElementStartRecord)
                    {
                        rootIndex = i + 1;
                        break;
                    }
                }
                Debug.Assert(rootIndex != -1);
            }
예제 #6
0
        public BamlDocument Analyze(ModuleDefMD module, string bamlName, byte[] data)
        {
            Module          = module;
            CurrentBAMLName = bamlName;
            if (module.IsClr40)
            {
                things = thingsv4 ?? (thingsv4 = new KnownThingsv4(context, module));
            }
            else
            {
                things = thingsv3 ?? (thingsv3 = new KnownThingsv3(context, module));
            }

            Debug.Assert(BitConverter.ToInt32(data, 0) == data.Length - 4);

            BamlDocument document = BamlReader.ReadDocument(new MemoryStream(data, 4, data.Length - 4));

            // Remove debug infos
            document.RemoveWhere(rec => rec is LineNumberAndPositionRecord || rec is LinePositionRecord);

            // Populate references
            PopulateReferences(document);

            // Process elements
            BamlElement rootElem = BamlElement.Read(document);
            BamlElement trueRoot = rootElem.Children.Single();
            var         stack    = new Stack <BamlElement>();

            stack.Push(rootElem);
            while (stack.Count > 0)
            {
                BamlElement elem = stack.Pop();
                ProcessBAMLElement(trueRoot, elem);
                foreach (BamlElement child in elem.Children)
                {
                    stack.Push(child);
                }
            }

            return(document);
        }
예제 #7
0
        public static void WriteDocument(BamlDocument doc, Stream str)
        {
            var writer = new BamlBinaryWriter(str);

            {
                var wtr = new BinaryWriter(str, Encoding.Unicode);
                int len = doc.Signature.Length * 2;
                wtr.Write(len);
                wtr.Write(doc.Signature.ToCharArray());
                wtr.Write(new byte[((len + 3) & ~3) - len]);
            }
            writer.Write(doc.ReaderVersion.Major);
            writer.Write(doc.ReaderVersion.Minor);
            writer.Write(doc.UpdaterVersion.Major);
            writer.Write(doc.UpdaterVersion.Minor);
            writer.Write(doc.WriterVersion.Major);
            writer.Write(doc.WriterVersion.Minor);

            var defers = new List <int>();

            for (int i = 0; i < doc.Count; i++)
            {
                BamlRecord rec = doc[i];
                rec.Position = str.Position;
                writer.Write((byte)rec.Type);
                rec.Write(writer);
                if (rec is IBamlDeferRecord)
                {
                    defers.Add(i);
                }
            }
            foreach (int i in defers)
            {
                (doc[i] as IBamlDeferRecord).WriteDefer(doc, i, writer);
            }
        }
예제 #8
0
 public void WriteDefer(BamlDocument doc, int index, BinaryWriter wtr)
 {
     wtr.BaseStream.Seek(pos, SeekOrigin.Begin);
     wtr.Write((uint)(Record.Position - (pos + 4)));
 }
예제 #9
0
 public void ReadDefer(BamlDocument doc, int index, Func <long, BamlRecord> resolve)
 {
     Record = resolve(pos + size);
 }
예제 #10
0
        public static BamlDocument ReadDocument(Stream str)
        {
            var ret    = new BamlDocument();
            var reader = new BamlBinaryReader(str);

            {
                var  rdr = new BinaryReader(str, Encoding.Unicode);
                uint len = rdr.ReadUInt32();
                ret.Signature = new string(rdr.ReadChars((int)(len >> 1)));
                rdr.ReadBytes((int)(((len + 3) & ~3) - len));
            }
            if (ret.Signature != "MSBAML")
            {
                throw new NotSupportedException();
            }
            ret.ReaderVersion = new BamlDocument.BamlVersion {
                Major = reader.ReadUInt16(), Minor = reader.ReadUInt16()
            };
            ret.UpdaterVersion = new BamlDocument.BamlVersion {
                Major = reader.ReadUInt16(), Minor = reader.ReadUInt16()
            };
            ret.WriterVersion = new BamlDocument.BamlVersion {
                Major = reader.ReadUInt16(), Minor = reader.ReadUInt16()
            };
            if (ret.ReaderVersion.Major != 0 || ret.ReaderVersion.Minor != 0x60 ||
                ret.UpdaterVersion.Major != 0 || ret.UpdaterVersion.Minor != 0x60 ||
                ret.WriterVersion.Major != 0 || ret.WriterVersion.Minor != 0x60)
            {
                throw new NotSupportedException();
            }

            var recs = new Dictionary <long, BamlRecord>();

            while (str.Position < str.Length)
            {
                long       pos  = str.Position;
                var        type = (BamlRecordType)reader.ReadByte();
                BamlRecord rec  = null;
                switch (type)
                {
                case BamlRecordType.AssemblyInfo:
                    rec = new AssemblyInfoRecord();
                    break;

                case BamlRecordType.AttributeInfo:
                    rec = new AttributeInfoRecord();
                    break;

                case BamlRecordType.ConstructorParametersStart:
                    rec = new ConstructorParametersStartRecord();
                    break;

                case BamlRecordType.ConstructorParametersEnd:
                    rec = new ConstructorParametersEndRecord();
                    break;

                case BamlRecordType.ConstructorParameterType:
                    rec = new ConstructorParameterTypeRecord();
                    break;

                case BamlRecordType.ConnectionId:
                    rec = new ConnectionIdRecord();
                    break;

                case BamlRecordType.ContentProperty:
                    rec = new ContentPropertyRecord();
                    break;

                case BamlRecordType.DefAttribute:
                    rec = new DefAttributeRecord();
                    break;

                case BamlRecordType.DefAttributeKeyString:
                    rec = new DefAttributeKeyStringRecord();
                    break;

                case BamlRecordType.DefAttributeKeyType:
                    rec = new DefAttributeKeyTypeRecord();
                    break;

                case BamlRecordType.DeferableContentStart:
                    rec = new DeferableContentStartRecord();
                    break;

                case BamlRecordType.DocumentEnd:
                    rec = new DocumentEndRecord();
                    break;

                case BamlRecordType.DocumentStart:
                    rec = new DocumentStartRecord();
                    break;

                case BamlRecordType.ElementEnd:
                    rec = new ElementEndRecord();
                    break;

                case BamlRecordType.ElementStart:
                    rec = new ElementStartRecord();
                    break;

                case BamlRecordType.KeyElementEnd:
                    rec = new KeyElementEndRecord();
                    break;

                case BamlRecordType.KeyElementStart:
                    rec = new KeyElementStartRecord();
                    break;

                case BamlRecordType.LineNumberAndPosition:
                    rec = new LineNumberAndPositionRecord();
                    break;

                case BamlRecordType.LinePosition:
                    rec = new LinePositionRecord();
                    break;

                case BamlRecordType.LiteralContent:
                    rec = new LiteralContentRecord();
                    break;

                case BamlRecordType.NamedElementStart:
                    rec = new NamedElementStartRecord();
                    break;

                case BamlRecordType.OptimizedStaticResource:
                    rec = new OptimizedStaticResourceRecord();
                    break;

                case BamlRecordType.PIMapping:
                    rec = new PIMappingRecord();
                    break;

                case BamlRecordType.PresentationOptionsAttribute:
                    rec = new PresentationOptionsAttributeRecord();
                    break;

                case BamlRecordType.Property:
                    rec = new PropertyRecord();
                    break;

                case BamlRecordType.PropertyArrayEnd:
                    rec = new PropertyArrayEndRecord();
                    break;

                case BamlRecordType.PropertyArrayStart:
                    rec = new PropertyArrayStartRecord();
                    break;

                case BamlRecordType.PropertyComplexEnd:
                    rec = new PropertyComplexEndRecord();
                    break;

                case BamlRecordType.PropertyComplexStart:
                    rec = new PropertyComplexStartRecord();
                    break;

                case BamlRecordType.PropertyCustom:
                    rec = new PropertyCustomRecord();
                    break;

                case BamlRecordType.PropertyDictionaryEnd:
                    rec = new PropertyDictionaryEndRecord();
                    break;

                case BamlRecordType.PropertyDictionaryStart:
                    rec = new PropertyDictionaryStartRecord();
                    break;

                case BamlRecordType.PropertyListEnd:
                    rec = new PropertyListEndRecord();
                    break;

                case BamlRecordType.PropertyListStart:
                    rec = new PropertyListStartRecord();
                    break;

                case BamlRecordType.PropertyStringReference:
                    rec = new PropertyStringReferenceRecord();
                    break;

                case BamlRecordType.PropertyTypeReference:
                    rec = new PropertyTypeReferenceRecord();
                    break;

                case BamlRecordType.PropertyWithConverter:
                    rec = new PropertyWithConverterRecord();
                    break;

                case BamlRecordType.PropertyWithExtension:
                    rec = new PropertyWithExtensionRecord();
                    break;

                case BamlRecordType.PropertyWithStaticResourceId:
                    rec = new PropertyWithStaticResourceIdRecord();
                    break;

                case BamlRecordType.RoutedEvent:
                    rec = new RoutedEventRecord();
                    break;

                case BamlRecordType.StaticResourceEnd:
                    rec = new StaticResourceEndRecord();
                    break;

                case BamlRecordType.StaticResourceId:
                    rec = new StaticResourceIdRecord();
                    break;

                case BamlRecordType.StaticResourceStart:
                    rec = new StaticResourceStartRecord();
                    break;

                case BamlRecordType.StringInfo:
                    rec = new StringInfoRecord();
                    break;

                case BamlRecordType.Text:
                    rec = new TextRecord();
                    break;

                case BamlRecordType.TextWithConverter:
                    rec = new TextWithConverterRecord();
                    break;

                case BamlRecordType.TextWithId:
                    rec = new TextWithIdRecord();
                    break;

                case BamlRecordType.TypeInfo:
                    rec = new TypeInfoRecord();
                    break;

                case BamlRecordType.TypeSerializerInfo:
                    rec = new TypeSerializerInfoRecord();
                    break;

                case BamlRecordType.XmlnsProperty:
                    rec = new XmlnsPropertyRecord();
                    break;

                case BamlRecordType.XmlAttribute:
                case BamlRecordType.ProcessingInstruction:
                case BamlRecordType.LastRecordType:
                case BamlRecordType.EndAttributes:
                case BamlRecordType.DefTag:
                case BamlRecordType.ClrEvent:
                case BamlRecordType.Comment:
                default:
                    throw new NotSupportedException();
                }
                rec.Position = pos;

                rec.Read(reader);
                ret.Add(rec);
                recs.Add(pos, rec);
            }
            for (int i = 0; i < ret.Count; i++)
            {
                var defer = ret[i] as IBamlDeferRecord;
                if (defer != null)
                {
                    defer.ReadDefer(ret, i, _ => recs[_]);
                }
            }

            return(ret);
        }
예제 #11
0
        void PopulateReferences(BamlDocument document)
        {
            var clrNs = new Dictionary <string, List <Tuple <AssemblyDef, string> > >();

            assemblyRefs.Clear();
            foreach (AssemblyInfoRecord rec in document.OfType <AssemblyInfoRecord>())
            {
                AssemblyDef assembly = context.Resolver.ResolveThrow(rec.AssemblyFullName, Module);
                assemblyRefs.Add(rec.AssemblyId, assembly);

                if (!context.Modules.Any(m => m.Assembly == assembly))
                {
                    continue;
                }

                foreach (CustomAttribute attr in assembly.CustomAttributes.FindAll("System.Windows.Markup.XmlnsDefinitionAttribute"))
                {
                    clrNs.AddListEntry(
                        (UTF8String)attr.ConstructorArguments[0].Value,
                        Tuple.Create(assembly, (string)(UTF8String)attr.ConstructorArguments[1].Value));
                }
            }

            xmlnsCtx = new XmlNsContext(document, assemblyRefs);

            typeRefs.Clear();
            foreach (TypeInfoRecord rec in document.OfType <TypeInfoRecord>())
            {
                AssemblyDef assembly;
                var         asmId = (short)(rec.AssemblyId & 0xfff);
                if (asmId == -1)
                {
                    assembly = things.FrameworkAssembly;
                }
                else
                {
                    assembly = assemblyRefs[(ushort)asmId];
                }

                AssemblyDef assemblyRef = Module.Assembly == assembly ? null : assembly;

                TypeSig typeSig = TypeNameParser.ParseAsTypeSigReflectionThrow(Module, rec.TypeFullName, new DummyAssemblyRefFinder(assemblyRef));
                typeRefs[rec.TypeId] = typeSig;

                AddTypeSigReference(typeSig, new BAMLTypeReference(typeSig, rec));
            }

            attrRefs.Clear();
            foreach (AttributeInfoRecord rec in document.OfType <AttributeInfoRecord>())
            {
                TypeSig declType;
                if (typeRefs.TryGetValue(rec.OwnerTypeId, out declType))
                {
                    TypeDef type = declType.ToBasicTypeDefOrRef().ResolveTypeDefThrow();
                    attrRefs[rec.AttributeId] = AnalyzeAttributeReference(type, rec);
                }
                else
                {
                    Debug.Assert((short)rec.OwnerTypeId < 0);
                    TypeDef declTypeDef = things.Types((KnownTypes)(-(short)rec.OwnerTypeId));
                    attrRefs[rec.AttributeId] = AnalyzeAttributeReference(declTypeDef, rec);
                }
            }

            strings.Clear();
            foreach (StringInfoRecord rec in document.OfType <StringInfoRecord>())
            {
                strings[rec.StringId] = rec;
            }

            foreach (PIMappingRecord rec in document.OfType <PIMappingRecord>())
            {
                var         asmId = (short)(rec.AssemblyId & 0xfff);
                AssemblyDef assembly;
                if (asmId == -1)
                {
                    assembly = things.FrameworkAssembly;
                }
                else
                {
                    assembly = assemblyRefs[(ushort)asmId];
                }

                Tuple <AssemblyDef, string> scope = Tuple.Create(assembly, rec.ClrNamespace);
                clrNs.AddListEntry(rec.XmlNamespace, scope);
            }

            xmlns.Clear();
            foreach (XmlnsPropertyRecord rec in document.OfType <XmlnsPropertyRecord>())
            {
                List <Tuple <AssemblyDef, string> > clrMap;
                if (clrNs.TryGetValue(rec.XmlNamespace, out clrMap))
                {
                    xmlns[rec.Prefix] = clrMap;
                    foreach (var scope in clrMap)
                    {
                        xmlnsCtx.AddNsMap(scope, rec.Prefix);
                    }
                }
            }
        }