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)); }
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); }
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); }
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++; } }
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); }
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); }
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); } }
public void WriteDefer(BamlDocument doc, int index, BinaryWriter wtr) { wtr.BaseStream.Seek(pos, SeekOrigin.Begin); wtr.Write((uint)(Record.Position - (pos + 4))); }
public void ReadDefer(BamlDocument doc, int index, Func <long, BamlRecord> resolve) { Record = resolve(pos + size); }
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); }
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); } } } }