private void ReadNodeInNodeSection(BinaryReaderEx reader, XbfNodeSection nodeSection, int offset) { // Save the current position and skip ahead to the new position long originalPosition = reader.BaseStream.Position; int newPosition = _firstNodeSectionPosition + nodeSection.NodeOffset; int newEndPosition = _firstNodeSectionPosition + nodeSection.PositionalOffset; reader.BaseStream.Position = newPosition + offset; int objectStackDepthBefore = _objectStack.Count; int objectCollectionStackDepthBefore = _objectCollectionStack.Count; // Read the node from the specified position ReadNodes(reader, int.MaxValue, false, true); if (_objectStack.Count != objectStackDepthBefore) { throw new InvalidDataException("_objectStack corrupted"); } if (_objectCollectionStack.Count != objectCollectionStackDepthBefore) { throw new InvalidDataException("_objectCollectionStack corrupted"); } // Return to the original position reader.BaseStream.Position = originalPosition; }
private void ReadDataTemplate(BinaryReaderEx reader) { string propertyName = GetPropertyName(reader.ReadUInt16()); // Always "Template" XbfNodeSection nodeSection = NodeSectionTable[reader.Read7BitEncodedInt()]; // List of StaticResources and ThemeResources referenced from inside the DataTemplate int staticResourceCount = reader.Read7BitEncodedInt(); int themeResourceCount = reader.Read7BitEncodedInt(); for (int i = 0; i < staticResourceCount; i++) { string staticResource = StringTable[reader.ReadUInt16()]; } for (int i = 0; i < themeResourceCount; i++) { string themeResource = StringTable[reader.ReadUInt16()]; } ReadNodeSection(reader, nodeSection); // Add the object we found as a property var obj = _objectStack.Pop(); _objectStack.Peek().Properties.Add(new XbfObjectProperty(propertyName, obj)); }
private void ReadResourceDictionary(BinaryReaderEx reader, XbfNodeSection nodeSection, bool extended) { // Resources with keys int resourcesCount = reader.Read7BitEncodedInt(); for (int i = 0; i < resourcesCount; i++) { string resourceKey = StringTable[reader.ReadUInt16()]; int position = reader.Read7BitEncodedInt(); // Secondary node stream offset XbfObject obj = ReadObjectInNodeSection(reader, nodeSection, position); obj.Key = resourceKey; _objectCollectionStack.Peek().Add(obj); } // A subset of the resource keys from above seem to get repeated here, purpose unknown int count = reader.Read7BitEncodedInt(); for (int i = 0; i < count; i++) { string resourceKey = StringTable[reader.ReadUInt16()]; } // Styles with TargetType and no key int styleCount = reader.Read7BitEncodedInt(); for (int i = 0; i < styleCount; i++) { string targetType = StringTable[reader.ReadUInt16()]; int position = reader.Read7BitEncodedInt(); // Secondary node stream offset XbfObject obj = ReadObjectInNodeSection(reader, nodeSection, position); _objectCollectionStack.Peek().Add(obj); } if (extended) { if (reader.Read7BitEncodedInt() != 0) // TODO: purpose unknown { throw new InvalidDataException("Unexpected value"); } } // A subset of the target types from above seem to get repeated here, purpose unknown int count2 = reader.Read7BitEncodedInt(); for (int i = 0; i < count2; i++) { string targetType = StringTable[reader.ReadUInt16()]; } }
private void ReadNodeSection(BinaryReaderEx reader, XbfNodeSection nodeSection) { // Save the current position and skip ahead to the new position long originalPosition = reader.BaseStream.Position; int newPosition = _firstNodeSectionPosition + nodeSection.NodeOffset; int newEndPosition = _firstNodeSectionPosition + nodeSection.PositionalOffset; reader.BaseStream.Position = newPosition; // Read the nodes from the specified position ReadNodes(reader, newEndPosition); // Return to the original position reader.BaseStream.Position = originalPosition; }
private void ReadNodeSectionReference(BinaryReaderEx reader) { // The node section we're skipping to XbfNodeSection nodeSection = NodeSectionTable[reader.Read7BitEncodedInt()]; if (reader.ReadUInt16() != 0) // TODO: unknown purpose { throw new InvalidDataException($"Unexpected value"); } // Get the type of nodes contained in this section int type = reader.Read7BitEncodedInt(); switch (type) { case 2: // Style case 8: // 8 seems to be equivalent ReadStyle(reader, nodeSection); break; case 7: // ResourceDictionary ReadResourceDictionary(reader, nodeSection, false); break; case 371: // ResourceDictionary ReadResourceDictionary(reader, nodeSection, true); break; case 5: // Visual states SkipVisualStateBytes(reader); ReadNodeSection(reader, nodeSection); break; case 6: // DeferredElement ReadDeferredElement(reader, nodeSection, true); break; case 746: // DeferredElement ReadDeferredElement(reader, nodeSection, false); break; default: throw new InvalidDataException(string.Format("Unknown node type {0} while parsing referenced code section", type)); } }
private void ReadDeferredElement(BinaryReaderEx reader, XbfNodeSection nodeSection, bool extended) { string deferredElementName = StringTable[reader.ReadUInt16()]; if (extended) { // The following properties can be ignored as they will appear in the secondary node section again int count = reader.Read7BitEncodedInt(); for (int i = 0; i < count; i++) { string propertyName = GetPropertyName(reader.ReadUInt16()); object propertyValue = GetPropertyValue(reader); } } ReadNodeSection(reader, nodeSection); XbfObject childObj = _objectStack.Pop(); XbfObject deferredElement = _objectStack.Peek(); deferredElement.Children.Add(childObj); }
private void ReadStyle(BinaryReaderEx reader, XbfNodeSection nodeSection) { int setterCount = reader.Read7BitEncodedInt(); for (int i = 0; i < setterCount; i++) { int valueType = reader.ReadByte(); string propertyName = null; string typeName = null; // Name of type implementing the property, currently ignored object propertyValue = null; int valueOffset = 0; switch (valueType) { case 0x01: // ThemeResource case 0x02: // StaticResource case 0x08: // General objects propertyName = StringTable[reader.ReadUInt16()]; typeName = GetTypeName(reader.ReadUInt16()); valueOffset = reader.Read7BitEncodedInt(); break; case 0x11: // ThemeResource case 0x12: // StaticResource case 0x18: // General objects propertyName = GetPropertyName(reader.ReadUInt16()); valueOffset = reader.Read7BitEncodedInt(); break; case 0x20: propertyName = StringTable[reader.ReadUInt16()]; typeName = GetTypeName(reader.ReadUInt16()); propertyValue = GetPropertyValue(reader); break; case 0x30: propertyName = GetPropertyName(reader.ReadUInt16()); propertyValue = GetPropertyValue(reader); break; default: throw new InvalidDataException("Unexpected value"); } // General objects can be read directly with ReadObjectInNodeSection if (valueType == 0x08 || valueType == 0x18) { propertyValue = ReadObjectInNodeSection(reader, nodeSection, valueOffset); } if (propertyValue != null) { var setter = new XbfObject(); setter.TypeName = "Setter"; setter.Properties.Add(new XbfObjectProperty("Property", propertyName)); setter.Properties.Add(new XbfObjectProperty("Value", propertyValue)); _objectCollectionStack.Peek().Add(setter); } else // StaticResource or ThemeResource need to be read with the Setter already on the stack { var setter = new XbfObject(); setter.TypeName = "Setter"; setter.Properties.Add(new XbfObjectProperty("Property", propertyName)); _objectCollectionStack.Peek().Add(setter); _objectStack.Push(setter); ReadNodeInNodeSection(reader, nodeSection, valueOffset); _objectStack.Pop(); } } }