Esempio n. 1
0
        public void ReplaceSelectedNodesWithType(Type type)
        {
            Contract.Requires(type != null);
            Contract.Requires(type.IsSubclassOf(typeof(BaseNode)));

            var selectedNodes = memoryViewControl.GetSelectedNodes();

            var newSelected = new List <MemoryViewControl.SelectedNodeInfo>(selectedNodes.Count);

            var hotSpotPartitions = selectedNodes
                                    .WhereNot(s => s.Node is ClassNode)
                                    .GroupBy(s => s.Node.GetParentContainer())
                                    .SelectMany(g => g
                                                .OrderBy(s => s.Node.Offset)
                                                .GroupWhile((h1, h2) => h1.Node.Offset + h1.Node.MemorySize == h2.Node.Offset)
                                                );

            foreach (var selectedPartition in hotSpotPartitions)
            {
                var hotSpotsToReplace = new Queue <MemoryViewControl.SelectedNodeInfo>(selectedPartition);
                while (hotSpotsToReplace.Count > 0)
                {
                    var selected = hotSpotsToReplace.Dequeue();

                    var node = BaseNode.CreateInstanceFromType(type);

                    var createdNodes = new List <BaseNode>();
                    selected.Node.GetParentContainer().ReplaceChildNode(selected.Node, node, ref createdNodes);

                    node.IsSelected = true;

                    var info = new MemoryViewControl.SelectedNodeInfo(node, selected.Memory, selected.Address, selected.Level);

                    newSelected.Add(info);

                    // If more than one node is selected I assume the user wants to replace the complete range with the desired node type.
                    if (selectedNodes.Count > 1)
                    {
                        foreach (var createdNode in createdNodes)
                        {
                            hotSpotsToReplace.Enqueue(new MemoryViewControl.SelectedNodeInfo(createdNode, selected.Memory, selected.Address + createdNode.Offset - node.Offset, selected.Level));
                        }
                    }
                }
            }

            memoryViewControl.ClearSelection();

            if (newSelected.Count > 0)
            {
                memoryViewControl.SetSelectedNodes(newSelected);
            }
        }
        public BaseNode CreateNodeFromElement(XElement element, BaseNode parent, IEnumerable <ClassNode> classes, ILogger logger, CreateNodeFromElementHandler createNodeFromElement)
        {
            if (!stringToTypeMap.TryGetValue(element.Attribute(ReClassNetFile.XmlTypeAttribute)?.Value ?? string.Empty, out var nodeType))
            {
                logger.Log(LogLevel.Error, $"Skipping node with unknown type: {element.Attribute(ReClassNetFile.XmlTypeAttribute)?.Value}");
                logger.Log(LogLevel.Warning, element.ToString());

                return(null);
            }

            return(BaseNode.CreateInstanceFromType(nodeType, false));
        }
Esempio n. 3
0
        private static void GetNodeInfoFromType(Type nodeType, out string label, out Image icon)
        {
            Contract.Requires(nodeType != null);

            var node = BaseNode.CreateInstanceFromType(nodeType, false);

            if (node == null)
            {
                throw new InvalidOperationException($"'{nodeType}' is not a valid node type.");
            }

            node.GetUserInterfaceInfo(out label, out icon);
        }
Esempio n. 4
0
        private void memoryViewControl_ChangeWrappedTypeClick(object sender, NodeClickEventArgs e)
        {
            if (e.Node is BaseWrapperNode wrapperNode)
            {
                var items = NodeTypesBuilder.CreateToolStripMenuItems(t =>
                {
                    var node = BaseNode.CreateInstanceFromType(t);
                    if (wrapperNode.CanChangeInnerNodeTo(node))
                    {
                        wrapperNode.ChangeInnerNode(node);
                    }
                }, wrapperNode.CanChangeInnerNodeTo(null));

                var menu = new ContextMenuStrip();
                menu.Items.AddRange(items.ToArray());
                menu.Show(this, e.Location);
            }
        }
Esempio n. 5
0
        private BaseNode CreateNodeFromElement(XElement element, BaseNode parent, ILogger logger)
        {
            Contract.Requires(element != null);
            Contract.Requires(logger != null);

            BaseNode CreateNode()
            {
                var converter = CustomNodeSerializer.GetReadConverter(element);

                if (converter != null)
                {
                    return(converter.CreateNodeFromElement(element, parent, project.Classes, logger, CreateNodeFromElement));
                }

                if (!buildInStringToTypeMap.TryGetValue(element.Attribute(XmlTypeAttribute)?.Value ?? string.Empty, out var nodeType))
                {
                    logger.Log(LogLevel.Error, $"Skipping node with unknown type: {element.Attribute(XmlTypeAttribute)?.Value}");
                    logger.Log(LogLevel.Warning, element.ToString());

                    return(null);
                }

                return(BaseNode.CreateInstanceFromType(nodeType, false));
            }

            var node = CreateNode();

            if (node == null)
            {
                logger.Log(LogLevel.Error, "Could not create node.");

                return(null);
            }

            node.ParentNode = parent;

            node.Name     = element.Attribute(XmlNameAttribute)?.Value ?? string.Empty;
            node.Comment  = element.Attribute(XmlCommentAttribute)?.Value ?? string.Empty;
            node.IsHidden = bool.TryParse(element.Attribute(XmlHiddenAttribute)?.Value, out var val) && val;

            if (node is BaseWrapperNode wrapperNode)
            {
                ClassNode GetClassNodeFromElementReference()
                {
                    var reference = NodeUuid.FromBase64String(element.Attribute(XmlReferenceAttribute)?.Value, false);

                    if (!project.ContainsClass(reference))
                    {
                        logger.Log(LogLevel.Error, $"Skipping node with unknown reference: {reference}");
                        logger.Log(LogLevel.Warning, element.ToString());

                        return(null);
                    }

                    return(project.GetClassByUuid(reference));
                }

                // Legacy Support
                if (node is ClassPointerNode || node is ClassInstanceArrayNode || node is ClassPointerArrayNode)
                {
                    var innerClass = GetClassNodeFromElementReference();
                    if (innerClass == null)
                    {
                        return(null);
                    }

                    switch (node)
                    {
                    case BaseClassArrayNode classArrayNode:
                        node = classArrayNode.GetEquivalentNode(0, innerClass);
                        break;

                    case ClassPointerNode classPointerNode:
                        node = classPointerNode.GetEquivalentNode(innerClass);
                        break;
                    }
                }
                else
                {
                    BaseNode innerNode = null;

                    if (node is BaseClassWrapperNode)
                    {
                        innerNode = GetClassNodeFromElementReference();
                        if (innerNode == null)
                        {
                            return(null);
                        }
                    }
                    else
                    {
                        var innerElement = element.Elements().FirstOrDefault();
                        if (innerElement != null)
                        {
                            innerNode = CreateNodeFromElement(innerElement, node, logger);
                        }
                    }

                    if (wrapperNode.CanChangeInnerNodeTo(innerNode))
                    {
                        var rootWrapperNode = node.GetRootWrapperNode();
                        if (rootWrapperNode.ShouldPerformCycleCheckForInnerNode() &&
                            innerNode is ClassNode classNode &&
                            ClassUtil.IsCyclicIfClassIsAccessibleFromParent(node.GetParentClass(), classNode, project.Classes))
                        {
                            logger.Log(LogLevel.Error, $"Skipping node with cyclic class reference: {node.GetParentClass().Name}->{rootWrapperNode.Name}");

                            return(null);
                        }

                        wrapperNode.ChangeInnerNode(innerNode);
                    }
                    else
                    {
                        logger.Log(LogLevel.Error, $"The node {innerNode} is not a valid child for {node}.");
                    }
                }
            }

            switch (node)
            {
            case VirtualMethodTableNode vtableNode:
            {
                var nodes = element
                            .Elements(XmlMethodElement)
                            .Select(e => new VirtualMethodNode
                    {
                        Name     = e.Attribute(XmlNameAttribute)?.Value ?? string.Empty,
                        Comment  = e.Attribute(XmlCommentAttribute)?.Value ?? string.Empty,
                        IsHidden = e.Attribute(XmlHiddenAttribute)?.Value.Equals("True") ?? false
                    });

                foreach (var vmethodNode in nodes)
                {
                    vtableNode.AddNode(vmethodNode);
                }
                break;
            }

            case BaseWrapperArrayNode arrayNode:
            {
                TryGetAttributeValue(element, XmlCountAttribute, out var count, logger);
                arrayNode.Count = count;
                break;
            }

            case BaseTextNode textNode:
            {
                TryGetAttributeValue(element, XmlLengthAttribute, out var length, logger);
                textNode.Length = length;
                break;
            }

            case BitFieldNode bitFieldNode:
            {
                TryGetAttributeValue(element, XmlBitsAttribute, out var bits, logger);
                bitFieldNode.Bits = bits;
                break;
            }

            case FunctionNode functionNode:
            {
                functionNode.Signature = element.Attribute(XmlSignatureAttribute)?.Value ?? string.Empty;

                var reference = NodeUuid.FromBase64String(element.Attribute(XmlReferenceAttribute)?.Value, false);
                if (project.ContainsClass(reference))
                {
                    functionNode.BelongsToClass = project.GetClassByUuid(reference);
                }
                break;
            }
            }

            return(node);
        }
Esempio n. 6
0
        private IEnumerable <BaseNode> ReadNodeElements(IEnumerable <XElement> elements, ClassNode parent, IReadOnlyDictionary <string, ClassNode> classes, Type[] typeMap, ILogger logger)
        {
            Contract.Requires(elements != null);
            Contract.Requires(parent != null);
            Contract.Requires(classes != null);
            Contract.Requires(typeMap != null);
            Contract.Requires(logger != null);

            foreach (var element in elements)
            {
                Type nodeType = null;

                if (int.TryParse(element.Attribute("Type")?.Value, out var typeVal))
                {
                    if (typeVal >= 0 && typeVal < typeMap.Length)
                    {
                        nodeType = typeMap[typeVal];
                    }
                }

                if (nodeType == null)
                {
                    logger.Log(LogLevel.Error, $"Skipping node with unknown type: {element.Attribute("Type")?.Value}");
                    logger.Log(LogLevel.Warning, element.ToString());

                    continue;
                }

                var node = BaseNode.CreateInstanceFromType(nodeType, false);
                if (node == null)
                {
                    logger.Log(LogLevel.Error, $"Could not create node of type: {nodeType}");

                    continue;
                }

                node.Name     = element.Attribute("Name")?.Value ?? string.Empty;
                node.Comment  = element.Attribute("Comment")?.Value ?? string.Empty;
                node.IsHidden = element.Attribute("bHidden")?.Value.Equals("1") ?? false;

                // Convert the Custom node into normal hex nodes.
                if (node is CustomNode customNode)
                {
                    int.TryParse(element.Attribute("Size")?.Value, out var size);

                    foreach (var paddingNode in customNode.GetEquivalentNodes(size))
                    {
                        yield return(paddingNode);
                    }

                    continue;
                }

                // ClassInstanceNode, ClassPointerNode, ClassInstanceArrayNode, ClassPointerArrayNode
                if (node is BaseWrapperNode baseWrapperNode)
                {
                    string reference;
                    int    arrayCount = 0;
                    if (node is BaseClassArrayNode)                     // ClassInstanceArrayNode, ClassPointerArrayNode
                    {
                        reference = element.Element("Array")?.Attribute("Name")?.Value;

                        if (node is ClassInstanceArrayNode)
                        {
                            TryGetAttributeValue(element, "Total", out arrayCount, logger);
                        }
                        else
                        {
                            TryGetAttributeValue(element, "Count", out arrayCount, logger);
                        }
                    }
                    else                     // ClassInstanceNode, ClassPointerNode
                    {
                        reference = element.Attribute("Pointer")?.Value ?? element.Attribute("Instance")?.Value;
                    }

                    if (reference == null || !classes.ContainsKey(reference))
                    {
                        logger.Log(LogLevel.Error, $"Skipping node with unknown reference: {reference}");
                        logger.Log(LogLevel.Warning, element.ToString());

                        continue;
                    }

                    var innerClassNode = classes[reference];
                    if (baseWrapperNode.ShouldPerformCycleCheckForInnerNode() && !ClassUtil.IsCyclicIfClassIsAccessibleFromParent(parent, innerClassNode, project.Classes))
                    {
                        logger.Log(LogLevel.Error, $"Skipping node with cycle reference: {parent.Name}->{node.Name}");

                        continue;
                    }

                    // ClassPointerNode, ClassInstanceArrayNode and ClassPointerArrayNode need to be converted to supported nodes.
                    if (node is BaseClassArrayNode classArrayNode)                     // ClassInstanceArrayNode, ClassPointerArrayNode
                    {
                        node = classArrayNode.GetEquivalentNode(arrayCount, innerClassNode);
                    }
                    else if (node is ClassPointerNode classPointerNode)                     // ClassPointerNode
                    {
                        node = classPointerNode.GetEquivalentNode(innerClassNode);
                    }
                    else                     // ClassInstanceNode, ClassPointerNode
                    {
                        baseWrapperNode.ChangeInnerNode(innerClassNode);
                    }
                }

                switch (node)
                {
                case VirtualMethodTableNode vtableNode:
                    element
                    .Elements("Function")
                    .Select(e => new VirtualMethodNode
                    {
                        Name     = e.Attribute("Name")?.Value ?? string.Empty,
                        Comment  = e.Attribute("Comment")?.Value ?? string.Empty,
                        IsHidden = e.Attribute("bHidden")?.Value.Equals("1") ?? false
                    })
                    .ForEach(vtableNode.AddNode);
                    break;

                case BaseTextNode textNode:
                {
                    TryGetAttributeValue(element, "Size", out var length, logger);
                    textNode.Length = textNode is Utf16TextNode ? length / 2 : length;
                    break;
                }

                case BitFieldNode bitFieldNode:
                {
                    TryGetAttributeValue(element, "Size", out var bits, logger);
                    bitFieldNode.Bits = bits * 8;
                    break;
                }
                }

                yield return(node);
            }
        }
Esempio n. 7
0
        private static IEnumerable <BaseNode> ReadNodeRows(IEnumerable <DataRow> rows, ClassNode parent, IReadOnlyDictionary <int, ClassNode> classes, IReadOnlyDictionary <int, VirtualMethodTableNode> vtables, ILogger logger)
        {
            Contract.Requires(rows != null);
            Contract.Requires(parent != null);
            Contract.Requires(logger != null);

            foreach (var row in rows)
            {
                Type nodeType = null;

                var typeVal = Convert.ToInt32(row["type"]);
                if (typeVal >= 0 && typeVal < typeMap.Length)
                {
                    nodeType = typeMap[typeVal];
                }

                if (nodeType == null)
                {
                    logger.Log(LogLevel.Error, $"Skipping node with unknown type: {row["type"]}");
                    logger.Log(LogLevel.Warning, string.Join(",", row.ItemArray));

                    continue;
                }

                var node = BaseNode.CreateInstanceFromType(nodeType, false);
                if (node == null)
                {
                    logger.Log(LogLevel.Error, $"Could not create node of type: {nodeType}");

                    continue;
                }

                node.Name    = Convert.ToString(row["variable"]);
                node.Comment = Convert.ToString(row["comment"]);

                // ClassInstanceNode, ClassPointerNode
                if (node is BaseWrapperNode wrapperNode)
                {
                    var reference = Convert.ToInt32(row["ref"]);
                    if (!classes.ContainsKey(reference))
                    {
                        if (!vtables.TryGetValue(reference, out var vtableNode))
                        {
                            logger.Log(LogLevel.Error, $"Skipping node with unknown reference: {row["ref"]}");
                            logger.Log(LogLevel.Warning, string.Join(",", row.ItemArray));

                            continue;
                        }

                        yield return(vtableNode);

                        continue;
                    }

                    var innerClassNode = classes[reference];
                    if (wrapperNode.ShouldPerformCycleCheckForInnerNode() && !ClassUtil.IsCyclicIfClassIsAccessibleFromParent(parent, innerClassNode, classes.Values))
                    {
                        logger.Log(LogLevel.Error, $"Skipping node with cycle reference: {parent.Name}->{node.Name}");

                        continue;
                    }

                    if (node is ClassPointerNode classPointerNode)
                    {
                        node = classPointerNode.GetEquivalentNode(innerClassNode);
                    }
                    else
                    {
                        wrapperNode.ChangeInnerNode(innerClassNode);
                    }
                }
                if (node is BaseTextNode textNode)
                {
                    textNode.Length = Math.Max(IntPtr.Size, Convert.ToInt32(row["length"]));
                }

                yield return(node);
            }
        }
Esempio n. 8
0
        private IEnumerable <BaseNode> ReadNodeElements(IEnumerable <XElement> elements, ClassNode parent, IReadOnlyDictionary <string, ClassNode> classes, ILogger logger)
        {
            Contract.Requires(elements != null);
            Contract.Requires(Contract.ForAll(elements, e => e != null));
            Contract.Requires(parent != null);
            Contract.Requires(logger != null);

            foreach (var element in elements)
            {
                Type nodeType = null;

                if (int.TryParse(element.Attribute("Type")?.Value, out var typeVal))
                {
                    if (typeVal >= 0 && typeVal < typeMap.Length)
                    {
                        nodeType = typeMap[typeVal];
                    }
                }

                if (nodeType == null)
                {
                    logger.Log(LogLevel.Error, $"Skipping node with unknown type: {element.Attribute("Type")?.Value}");
                    logger.Log(LogLevel.Warning, element.ToString());

                    continue;
                }

                var node = BaseNode.CreateInstanceFromType(nodeType, false);
                if (node == null)
                {
                    logger.Log(LogLevel.Error, $"Could not create node of type: {nodeType}");

                    continue;
                }

                node.Name    = element.Attribute("Name")?.Value ?? string.Empty;
                node.Comment = element.Attribute("Comments")?.Value ?? string.Empty;

                // ClassInstanceNode, ClassPointerNode
                if (node is BaseWrapperNode wrapperNode)
                {
                    var pointToClassId = element.Attribute("PointToClass")?.Value;
                    if (pointToClassId == null || !classes.ContainsKey(pointToClassId))
                    {
                        logger.Log(LogLevel.Error, $"Skipping node with unknown reference: {pointToClassId}");
                        logger.Log(LogLevel.Warning, element.ToString());

                        continue;
                    }

                    var innerClassNode = classes[pointToClassId];
                    if (wrapperNode.ShouldPerformCycleCheckForInnerNode() && !ClassUtil.IsCyclicIfClassIsAccessibleFromParent(parent, innerClassNode, project.Classes))
                    {
                        logger.Log(LogLevel.Error, $"Skipping node with cycle reference: {parent.Name}->{node.Name}");

                        continue;
                    }

                    if (node is ClassPointerNode classPointerNode)
                    {
                        node = classPointerNode.GetEquivalentNode(innerClassNode);
                    }
                    else                     // ClassInstanceNode
                    {
                        wrapperNode.ChangeInnerNode(innerClassNode);
                    }
                }

                yield return(node);
            }
        }