예제 #1
0
        public static bool GetVirtualFunctionPatterns(string name, ref VirtualFunctionPatterns patterns)
        {
            if (!_virtualFunctionPattern.ContainsKey(name))
            {
                return(false);
            }

            patterns = _virtualFunctionPattern[name];
            return(true);
        }
예제 #2
0
        /// <summary>
        /// Generates the class.
        /// </summary>
        /// <param name="classObj">The class object.</param>
        private async Task GenerateClass(GenericTypes.UEClass classObj)
        {
            var c = new Class
            {
                Name     = await classObj.GetName(),
                FullName = await classObj.GetFullName()
            };

            var logTask = Logger.Log($"Class:   {await GetName() + "." + c.Name,-85} - instance: 0x{classObj.GetAddress().ToInt64():X8}");

            c.NameCpp     = NameValidator.MakeValidName(await classObj.GetNameCpp());
            c.NameCppFull = $"class {c.NameCpp}";

            c.Size = await classObj.GetPropertySize();

            c.InheritedSize = 0;

            int offset = 0;

            var super = await classObj.GetSuper();

            if (super.IsValid() && super != classObj)
            {
                c.InheritedSize = offset = await super.GetPropertySize();

                c.NameCppFull += $" : public {NameValidator.MakeValidName(await super.GetNameCpp())}";
            }

            var predefinedStaticMembers = new List <PredefinedMember>();

            if (Generator.GetPredefinedClassStaticMembers(c.FullName, ref predefinedStaticMembers))
            {
                foreach (var prop in predefinedStaticMembers)
                {
                    var p = new Member
                    {
                        Offset   = 0,
                        Size     = 0,
                        Name     = prop.Name,
                        Type     = prop.Type,
                        IsStatic = true
                    };
                    c.Members.Add(p);
                }
            }

            var predefinedMembers = new List <PredefinedMember>();

            if (Generator.GetPredefinedClassMembers(c.FullName, ref predefinedMembers))
            {
                foreach (var prop in predefinedMembers)
                {
                    var p = new Member
                    {
                        Offset   = 0,
                        Size     = 0,
                        Name     = prop.Name,
                        Type     = prop.Type,
                        IsStatic = false,
                        Comment  = "NOT AUTO-GENERATED PROPERTY"
                    };
                    c.Members.Add(p);
                }
            }
            else
            {
                var properties = new List <GenericTypes.UEProperty>();
                for (var prop = (await classObj.GetChildren()).Cast <GenericTypes.UEProperty>(); prop.IsValid(); prop = (await prop.GetNext()).Cast <GenericTypes.UEProperty>())
                {
                    var elementSizeT   = prop.GetElementSize();
                    var isScriptStruct = prop.IsA <GenericTypes.UEScriptStruct>();
                    var isFunction     = prop.IsA <GenericTypes.UEFunction>();
                    var isEnum         = prop.IsA <GenericTypes.UEEnum>();
                    var isConst        = prop.IsA <GenericTypes.UEConst>();

                    if (await elementSizeT > 0 &&
                        !await isScriptStruct &&
                        !await isFunction &&
                        !await isEnum &&
                        !await isConst &&
                        (!super.IsValid() || (super != classObj && await prop.GetOffset() >= await super.GetPropertySize())))
                    {
                        properties.Add(prop);
                    }
                }

                // As C# sort not same as C++ version, that's not work
                // Anyway after some testes it's not needed !!
                // properties.Sort((x, y) => ComparePropertyLess(x, y).Result ? 0 : 1);

                c.Members = await GenerateMembers(classObj, offset, properties);
            }

            Generator.GetPredefinedClassMethods(c.FullName, ref c.PredefinedMethods);

            if (Generator.SdkType == SdkType.External)
            {
                // ToDO: Add external Read/Write here for external
            }
            else
            {
                if (Generator.ShouldUseStrings)
                {
                    string classStr = Generator.ShouldXorStrings ? $"_xor_(\"{c.FullName}\")" : $"\"{c.FullName}\"";
                    c.PredefinedMethods.Add(PredefinedMethod.Inline($@"	static UClass* StaticClass()
	{{
		static auto ptr = UObject::FindClass({classStr});
		return ptr;
	}}"    )
                                            );
                }
                else
                {
                    c.PredefinedMethods.Add(PredefinedMethod.Inline($@"	static UClass* StaticClass()
	{{
		static auto ptr = UObject::GetObjectCasted<UClass>({classObj.GetIndex()});
		return ptr;
	}}"    )
                                            );
                }

                c.Methods = await GenerateMethods(classObj);

                //search virtual functions
                var patterns = new VirtualFunctionPatterns();
                if (Generator.GetVirtualFunctionPatterns(c.FullName, ref patterns))
                {
                    int    ptrSize       = Utils.GamePointerSize();
                    IntPtr vTableAddress = classObj.Object.VfTable;
                    var    vTable        = new List <IntPtr>();

                    int methodCount = 0;
                    while (methodCount < 150)
                    {
                        // Dereference Pointer
                        IntPtr vAddress = Utils.MemObj.ReadAddress(vTableAddress + (methodCount * ptrSize));

                        // Check valid address
                        int res = Win32.VirtualQueryEx(Utils.MemObj.ProcessHandle, vAddress, out var info, (uint)Marshal.SizeOf <Win32.MemoryBasicInformation>());
                        if (res == 0 || info.Protect.HasFlag(Win32.MemoryProtection.PageNoAccess))
                        {
                            break;
                        }

                        vTable.Add(vAddress);
                        methodCount++;
                    }

                    foreach (var(pattern, funcStr) in patterns)
                    {
                        for (int i = 0; i < methodCount; i++)
                        {
                            if (vTable[i].IsNull())
                            {
                                continue;
                            }

                            var scanResult = await PatternScanner.FindPattern(Utils.MemObj, vTable[i], vTable[i] + 0x300, new List <PatternScanner.Pattern> {
                                pattern
                            }, true);

                            if (!scanResult.ContainsKey(pattern.Name) || scanResult[pattern.Name].Empty())
                            {
                                continue;
                            }

                            c.PredefinedMethods.Add(PredefinedMethod.Inline($@"{funcStr.Replace("%d", i.ToString())}"));
                            break;
                        }
                    }
                }
            }

            // Wait logger
            await logTask;

            Classes.Add(c);
        }