Example #1
0
        internal static unsafe int Initialize(IntPtr managedFunctionsBuffer, IntPtr nativeFunctionsBuffer, IntPtr sharedFunctionsBuffer)
        {
            assembliesContextManager = new AssembliesContextManager();
            assembliesContextManager.CreateAssembliesContext();

            pluginLoaders = new Dictionary <int, PluginLoader>();

            unchecked {
                int     head             = 0;
                IntPtr *managedFunctions = (IntPtr *)managedFunctionsBuffer;

                Invoke    = GenerateOptimizedFunction <InvokeDelegate>(managedFunctions[head++]);
                Exception = GenerateOptimizedFunction <ExceptionDelegate>(managedFunctions[head++]);
                Log       = GenerateOptimizedFunction <LogDelegate>(managedFunctions[head++]);
            }

            unchecked {
                int     head            = 0;
                IntPtr *nativeFunctions = (IntPtr *)nativeFunctionsBuffer;

                nativeFunctions[head++] = typeof(Core).GetMethod("ExecuteAssemblyFunction", BindingFlags.NonPublic | BindingFlags.Static).MethodHandle.GetFunctionPointer();
                nativeFunctions[head++] = typeof(Core).GetMethod("LoadAssemblyFunction", BindingFlags.NonPublic | BindingFlags.Static).MethodHandle.GetFunctionPointer();
                nativeFunctions[head++] = typeof(Core).GetMethod("UnloadAssemblies", BindingFlags.NonPublic | BindingFlags.Static).MethodHandle.GetFunctionPointer();
            }

            sharedFunctions = sharedFunctionsBuffer;

            return(0xF);
        }
Example #2
0
		internal static void UnloadAssemblies() {
			try {
				plugin?.loader.Dispose();
				plugin = null;

				assembliesContextManager.UnloadAssembliesContext();
				assembliesContextManager = null;

				uint unloadAttempts = 0;

				while (assembliesContextWeakReference.IsAlive) {
					GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
					GC.WaitForPendingFinalizers();

					unloadAttempts++;

					if (unloadAttempts == 5000) {
						Log(LogLevel.Warning, "Unloading of assemblies took more time than expected. Trying to unload assemblies to the next breakpoint...");
					} else if (unloadAttempts == 10000) {
						Log(LogLevel.Error, "Unloading of assemblies was failed! This might be caused by running threads, strong GC handles, or by other sources that prevent cooperative unloading.");

						break;
					}
				}

				assembliesContextManager = new AssembliesContextManager();
				assembliesContextWeakReference = assembliesContextManager.CreateAssembliesContext();
			}

			catch (Exception exception) {
				Exception("Unloading of assemblies failed\r\n" + exception.ToString());
			}
		}
Example #3
0
        internal static unsafe int Initialize(IntPtr functions, int checksum)
        {
            assembliesContextManager = new AssembliesContextManager();
            assembliesContextManager.CreateAssembliesContext();

            plugins = new Dictionary <int, Plugin>();

            int     position = 0;
            IntPtr *buffer   = (IntPtr *)functions;

            unchecked {
                int     head             = 0;
                IntPtr *managedFunctions = (IntPtr *)buffer[position++];

                Invoke    = GenerateOptimizedFunction <InvokeDelegate>(managedFunctions[head++]);
                Exception = GenerateOptimizedFunction <ExceptionDelegate>(managedFunctions[head++]);
                Log       = GenerateOptimizedFunction <LogDelegate>(managedFunctions[head++]);
            }

            unchecked {
                int     head            = 0;
                IntPtr *nativeFunctions = (IntPtr *)buffer[position++];

                nativeFunctions[head++] = typeof(Core).GetMethod("ExecuteAssemblyFunction", BindingFlags.NonPublic | BindingFlags.Static).MethodHandle.GetFunctionPointer();
                nativeFunctions[head++] = typeof(Core).GetMethod("LoadAssemblyFunction", BindingFlags.NonPublic | BindingFlags.Static).MethodHandle.GetFunctionPointer();
                nativeFunctions[head++] = typeof(Core).GetMethod("UnloadAssemblies", BindingFlags.NonPublic | BindingFlags.Static).MethodHandle.GetFunctionPointer();
            }

            sharedFunctions = buffer[position++];
            sharedChecksum  = checksum;

            return(0xF);
        }
Example #4
0
        internal static unsafe int Initialize(IntPtr functions, int checksum)
        {
            try {
                assembliesContextManager = new AssembliesContextManager();
                assembliesContextManager.CreateAssembliesContext();

                int     position = 0;
                IntPtr *buffer   = (IntPtr *)functions;

                unchecked {
                    int     head             = 0;
                    IntPtr *managedFunctions = (IntPtr *)buffer[position++];

                    Invoke         = GenerateOptimizedFunction <InvokeDelegate>(managedFunctions[head++]);
                    InvokeArgument = GenerateOptimizedFunction <InvokeArgumentDelegate>(managedFunctions[head++]);
                    Exception      = GenerateOptimizedFunction <ExceptionDelegate>(managedFunctions[head++]);
                    Log            = GenerateOptimizedFunction <LogDelegate>(managedFunctions[head++]);
                }

                unchecked {
                    int     head            = 0;
                    IntPtr *nativeFunctions = (IntPtr *)buffer[position++];

                    nativeFunctions[head++] = typeof(Core).GetMethod("ExecuteManagedFunction", BindingFlags.NonPublic | BindingFlags.Static).MethodHandle.GetFunctionPointer();
                    nativeFunctions[head++] = typeof(Core).GetMethod("ExecuteManagedFunctionArgument", BindingFlags.NonPublic | BindingFlags.Static).MethodHandle.GetFunctionPointer();
                    nativeFunctions[head++] = typeof(Core).GetMethod("FindManagedFunction", BindingFlags.NonPublic | BindingFlags.Static).MethodHandle.GetFunctionPointer();
                    nativeFunctions[head++] = typeof(Core).GetMethod("LoadAssemblies", BindingFlags.NonPublic | BindingFlags.Static).MethodHandle.GetFunctionPointer();
                    nativeFunctions[head++] = typeof(Core).GetMethod("UnloadAssemblies", BindingFlags.NonPublic | BindingFlags.Static).MethodHandle.GetFunctionPointer();
                }

                sharedFunctions = buffer[position++];
                sharedChecksum  = checksum;
            }

            catch (Exception exception) {
                Exception("Runtime initialization failed\r\n" + exception.ToString());
            }

            return(0xF);
        }
Example #5
0
        internal static unsafe IntPtr ManagedCommand(Command command)
        {
            if (command.type == CommandType.Execute)
            {
                try {
                    Invoke(command.function, command.value);
                }

                catch (Exception exception) {
                    Exception(exception.ToString());
                }

                return(IntPtr.Zero);
            }

            if (command.type == CommandType.Find)
            {
                IntPtr function = IntPtr.Zero;

                try {
                    string method = Marshal.PtrToStringAnsi(command.method);

                    if (plugin != null && !plugin.userFunctions.TryGetValue(method.GetHashCode(StringComparison.Ordinal), out function) && command.optional != 1)
                    {
                        Log(LogLevel.Error, "Managed function was not found \"" + method + "\"");
                    }
                }

                catch (Exception exception) {
                    Exception(exception.ToString());
                }

                return(function);
            }

            if (command.type == CommandType.Initialize)
            {
                try {
                    assembliesContextManager       = new AssembliesContextManager();
                    assembliesContextWeakReference = assembliesContextManager.CreateAssembliesContext();

                    int     position = 0;
                    IntPtr *buffer   = command.buffer;

                    unchecked {
                        int     head             = 0;
                        IntPtr *runtimeFunctions = (IntPtr *)buffer[position++];

                        Invoke    = GenerateOptimizedFunction <InvokeDelegate>(runtimeFunctions[head++]);
                        Exception = GenerateOptimizedFunction <ExceptionDelegate>(runtimeFunctions[head++]);
                        Log       = GenerateOptimizedFunction <LogDelegate>(runtimeFunctions[head++]);
                    }

                    sharedEvents    = buffer[position++];
                    sharedFunctions = buffer[position++];
                    sharedChecksum  = command.checksum;
                }

                catch (Exception exception) {
                    Exception("Runtime initialization failed\r\n" + exception.ToString());
                }

                return(new IntPtr(0xF));
            }

            if (command.type == CommandType.LoadAssemblies)
            {
                try {
                    const string frameworkName = "UnrealEngine.Framework";
                    string       assemblyPath  = Assembly.GetExecutingAssembly().Location;
                    string       managedFolder = assemblyPath.Substring(0, assemblyPath.IndexOf("Plugins", StringComparison.Ordinal)) + "Managed";
                    string[]     folders       = Directory.GetDirectories(managedFolder);

                    Array.Resize(ref folders, folders.Length + 1);

                    folders[folders.Length - 1] = managedFolder;

                    foreach (string folder in folders)
                    {
                        IEnumerable <string> assemblies = Directory.EnumerateFiles(folder, "*.dll", SearchOption.AllDirectories);

                        foreach (string assembly in assemblies)
                        {
                            AssemblyName name = null;

                            try {
                                name = AssemblyName.GetAssemblyName(assembly);
                            }

                            catch (BadImageFormatException) {
                                continue;
                            }

                            if (name?.Name != frameworkName)
                            {
                                plugin          = new Plugin();
                                plugin.loader   = PluginLoader.CreateFromAssemblyFile(assembly, config => { config.DefaultContext = assembliesContextManager.assembliesContext; config.IsUnloadable = true; });
                                plugin.assembly = plugin.loader.LoadAssemblyFromPath(assembly);

                                AssemblyName[] referencedAssemblies = plugin.assembly.GetReferencedAssemblies();

                                foreach (AssemblyName referencedAssembly in referencedAssemblies)
                                {
                                    if (referencedAssembly.Name == frameworkName)
                                    {
                                        Assembly framework = plugin.loader.LoadAssembly(referencedAssembly);

                                        using (assembliesContextManager.assembliesContext.EnterContextualReflection()) {
                                            Type sharedClass = framework.GetType(frameworkName + ".Shared");

                                            if ((int)sharedClass.GetField("checksum", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null) == sharedChecksum)
                                            {
                                                plugin.userFunctions = (Dictionary <int, IntPtr>)sharedClass.GetMethod("Load", BindingFlags.NonPublic | BindingFlags.Static).Invoke(null, new object[] { sharedEvents, sharedFunctions, plugin.assembly });

                                                Log(LogLevel.Display, "Framework loaded succesfuly for " + assembly);
                                            }
                                            else
                                            {
                                                Log(LogLevel.Fatal, "Framework loading failed, version is incompatible with the runtime, please, recompile the project with an updated version referenced in " + assembly);
                                            }
                                        }

                                        return(IntPtr.Zero);
                                    }
                                }

                                command.type = CommandType.UnloadAssemblies;

                                goto UnloadAssemblies;
                            }
                        }
                    }
                }

                catch (Exception exception) {
                    Exception("Loading of assemblies failed\r\n" + exception.ToString());
                }

                return(IntPtr.Zero);
            }

UnloadAssemblies:

            if (command.type == CommandType.UnloadAssemblies)
            {
                try {
                    plugin?.loader.Dispose();
                    plugin = null;

                    assembliesContextManager.UnloadAssembliesContext();
                    assembliesContextManager = null;

                    uint unloadAttempts = 0;

                    while (assembliesContextWeakReference.IsAlive)
                    {
                        GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
                        GC.WaitForPendingFinalizers();

                        unloadAttempts++;

                        if (unloadAttempts == 5000)
                        {
                            Log(LogLevel.Warning, "Unloading of assemblies took more time than expected. Trying to unload assemblies to the next breakpoint...");
                        }
                        else if (unloadAttempts == 10000)
                        {
                            Log(LogLevel.Error, "Unloading of assemblies was failed! This might be caused by running threads, strong GC handles, or by other sources that prevent cooperative unloading.");

                            break;
                        }
                    }

                    assembliesContextManager       = new AssembliesContextManager();
                    assembliesContextWeakReference = assembliesContextManager.CreateAssembliesContext();
                }

                catch (Exception exception) {
                    Exception("Unloading of assemblies failed\r\n" + exception.ToString());
                }

                return(IntPtr.Zero);
            }

            return(IntPtr.Zero);
        }