コード例 #1
0
        /// <summary>
        /// Unloads all DLLs and functions currently loaded
        /// </summary>
        public static void UnloadAll()
        {
            _nativeFunctionLoadLock.EnterWriteLock(); //Locking with no thread safety option is not required but is ok (this function isn't performance critical)
            try
            {
                foreach (var dll in _dlls.Values)
                {
                    if (dll.handle != IntPtr.Zero)
                    {
                        LowLevelPluginManager.OnBeforeDllUnload(dll);
                        InvokeCustomTriggers(_customBeforeUnloadTriggers, dll);

                        bool success = SysUnloadDll(dll.handle);
                        if (!success)
                        {
                            Debug.LogWarning($"Error while unloading DLL \"{dll.name}\" at path \"{dll.path}\"");
                        }

                        dll.ResetAsUnloaded();
                        InvokeCustomTriggers(_customAfterUnloadTriggers, dll);
                    }
                }
            }
            finally
            {
                _nativeFunctionLoadLock.ExitWriteLock();
            }
        }
コード例 #2
0
        /// <summary>
        /// Loads DLL and function delegate of <paramref name="nativeFunction"/> if not yet loaded.
        /// To achieve thread safety calls to this method must be synchronized.
        /// Note: This method is being called by dynamically generated code. Be careful when changing its signature.
        /// </summary>
        internal static void LoadTargetFunction(NativeFunction nativeFunction, bool ignoreLoadError)
        {
            var dll = nativeFunction.containingDll;

            if (dll.handle == IntPtr.Zero)
            {
                dll.handle = SysLoadDll(dll.path);
                if (dll.handle == IntPtr.Zero)
                {
                    if (!ignoreLoadError)
                    {
                        dll.loadingError = true;
#if UNITY_EDITOR
                        DispatchOnMainThread(() => { EditorApplication.isPaused = true; });
#endif
                        throw new NativeDllException($"Could not load DLL \"{dll.name}\" at path \"{dll.path}\".");
                    }

                    return;
                }
                else
                {
                    dll.loadingError = false;
                    LowLevelPluginManager.OnDllLoaded(dll);

                    // Call the custom triggers once UnityPluginLoad has been called
                    // For Lazy mode call the triggers immediately, preload waits until all functions are loaded (in LoadAll)
                    if (Options.loadingMode == DllLoadingMode.Lazy)
                    {
                        InvokeCustomTriggers(_customLoadedTriggers, dll);
                    }
                }
            }

            if (nativeFunction.@delegate == null)
            {
                IntPtr funcPtr = SysGetDllProcAddress(dll.handle, nativeFunction.identity.symbol);
                if (funcPtr == IntPtr.Zero)
                {
                    if (!ignoreLoadError)
                    {
                        dll.symbolError = true;
#if UNITY_EDITOR
                        DispatchOnMainThread(() => { EditorApplication.isPaused = true; });
#endif
                        throw new NativeDllException($"Could not get address of symbol \"{nativeFunction.identity.symbol}\" in DLL \"{dll.name}\" at path \"{dll.path}\".");
                    }

                    return;
                }
                else
                {
                    dll.symbolError = false;
                }

                nativeFunction.@delegate = Marshal.GetDelegateForFunctionPointer(funcPtr, nativeFunction.delegateType);
            }
        }
コード例 #3
0
        /// <summary>
        /// Loads DLL and function delegate of <paramref name="nativeFunction"/> if not yet loaded.
        /// To achieve thread safety calls to this method must be synchronized.
        /// Note: This method is being called by dynamically generated code. Be careful when changing its signature.
        /// </summary>
        internal static void LoadTargetFunction(NativeFunction nativeFunction, bool ignoreLoadError)
        {
            var dll = nativeFunction.containingDll;

            if (dll.handle == IntPtr.Zero)
            {
                dll.handle = SysLoadDll(dll.path);
                if (dll.handle == IntPtr.Zero)
                {
                    if (!ignoreLoadError)
                    {
                        dll.loadingError = true;
                        Prop_EditorApplication_isPaused.Value?.SetValue(null, true);
                        throw new NativeDllException($"Could not load DLL \"{dll.name}\" at path \"{dll.path}\".");
                    }

                    return;
                }
                else
                {
                    dll.loadingError = false;
                    InvokeCustomTriggers(_customLoadedTriggers, dll);
                    LowLevelPluginManager.OnDllLoaded(dll);
                }
            }

            if (nativeFunction.@delegate == null)
            {
                IntPtr funcPtr = SysGetDllProcAddress(dll.handle, nativeFunction.identity.symbol);
                if (funcPtr == IntPtr.Zero)
                {
                    if (!ignoreLoadError)
                    {
                        dll.symbolError = true;
                        Prop_EditorApplication_isPaused.Value?.SetValue(null, true);
                        throw new NativeDllException($"Could not get address of symbol \"{nativeFunction.identity.symbol}\" in DLL \"{dll.name}\" at path \"{dll.path}\".");
                    }

                    return;
                }
                else
                {
                    dll.symbolError = false;
                }

                nativeFunction.@delegate = Marshal.GetDelegateForFunctionPointer(funcPtr, nativeFunction.delegateType);
            }
        }
コード例 #4
0
        /// <summary>
        /// Initialization.
        /// Finds and mocks relevant native function declarations.
        /// If <see cref="DllLoadingMode.Preload"/> option is specified, loads all DLLs specified by these functions.
        /// Options have to be configured before calling this method.
        /// </summary>
        internal static void Initialize(int unityMainThreadId, string assetsPath)
        {
            _unityMainThreadId = unityMainThreadId;
            _assetsPath        = assetsPath;

            LowLevelPluginManager.ResetStubPlugin();

            Assembly[] assemblies;
            if (Options.assemblyPaths.Length == 0)
            {
                assemblies = new[] { Assembly.GetExecutingAssembly() };
            }
            else
            {
                var allAssemblies = AppDomain.CurrentDomain.GetAssemblies();
                assemblies = allAssemblies.Where(a => !a.IsDynamic && Options.assemblyPaths.Any(p => p == PathUtils.NormallizeSystemAssemblyPath(a.Location))).ToArray();
                var missingAssemblies = Options.assemblyPaths.Except(assemblies.Select(a => PathUtils.NormallizeSystemAssemblyPath(a.Location)));
                foreach (var assemblyPath in missingAssemblies)
                {
                    Debug.LogError($"Could not find assembly at path {assemblyPath}");
                }
            }

            foreach (var assembly in assemblies)
            {
                var allTypes = assembly.GetTypes();
                foreach (var type in allTypes)
                {
                    foreach (var method in type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))
                    {
                        if (method.IsDefined(typeof(DllImportAttribute)))
                        {
                            if (method.IsDefined(typeof(DisableMockingAttribute)))
                            {
                                continue;
                            }

                            if (method.DeclaringType.IsDefined(typeof(DisableMockingAttribute)))
                            {
                                continue;
                            }

                            if (Options.mockAllNativeFunctions || method.IsDefined(typeof(MockNativeDeclarationAttribute)) || method.DeclaringType.IsDefined(typeof(MockNativeDeclarationsAttribute)))
                            {
                                MockNativeFunction(method);
                            }
                        }
                        else if (method.IsDefined(typeof(NativeDllLoadedTriggerAttribute)))
                        {
                            RegisterTriggerMethod(method, ref _customLoadedTriggers);
                        }
                        else if (method.IsDefined(typeof(NativeDllBeforeUnloadTriggerAttribute)))
                        {
                            RegisterTriggerMethod(method, ref _customBeforeUnloadTriggers);
                        }
                        else if (method.IsDefined(typeof(NativeDllAfterUnloadTriggerAttribute)))
                        {
                            RegisterTriggerMethod(method, ref _customAfterUnloadTriggers);
                        }
                    }
                }
            }

            if (Options.loadingMode == DllLoadingMode.Preload)
            {
                LoadAll();
            }
        }
コード例 #5
0
        /// <summary>
        /// Initialization.
        /// Finds and mocks relevant native function declarations.
        /// If <see cref="DllLoadingMode.Preload"/> option is specified, loads all DLLs specified by these functions.
        /// Options have to be configured before calling this method.
        /// </summary>
        internal static void Initialize(DllManipulatorOptions options, int unityMainThreadId, string assetsPath)
        {
            // Make a deep copy of the options so we can edit them in DllManipulatorScript independently
            Options = new DllManipulatorOptions();
            options.CloneTo(Options);
            _unityMainThreadId = unityMainThreadId;
            _assetsPath        = assetsPath;

            LowLevelPluginManager.ResetStubPlugin();

            IEnumerable <string> assemblyPathsTemp = Options.assemblyNames;

            if (!assemblyPathsTemp.Any())
            {
                assemblyPathsTemp = DEFAULT_ASSEMBLY_NAMES;
            }

            assemblyPathsTemp = assemblyPathsTemp.Concat(INTERNAL_ASSEMBLY_NAMES);

            var allAssemblies     = AppDomain.CurrentDomain.GetAssemblies();
            var assemblies        = allAssemblies.Where(a => !a.IsDynamic && assemblyPathsTemp.Any(p => p == Path.GetFileNameWithoutExtension(a.Location))).ToArray();
            var missingAssemblies = assemblyPathsTemp.Except(assemblies.Select(a => Path.GetFileNameWithoutExtension(a.Location)));

            foreach (var assembly in missingAssemblies.Except(DEFAULT_ASSEMBLY_NAMES))
            {
                Debug.LogError($"Could not find assembly: {assembly}");
            }

            foreach (var assembly in assemblies)
            {
                var allTypes = assembly.GetTypes();
                foreach (var type in allTypes)
                {
                    foreach (var method in type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))
                    {
                        if (method.IsDefined(typeof(DllImportAttribute)))
                        {
                            if (method.IsDefined(typeof(DisableMockingAttribute)))
                            {
                                continue;
                            }

                            if (method.DeclaringType.IsDefined(typeof(DisableMockingAttribute)))
                            {
                                continue;
                            }

                            if (Options.mockAllNativeFunctions || method.IsDefined(typeof(MockNativeDeclarationAttribute)) || method.DeclaringType.IsDefined(typeof(MockNativeDeclarationsAttribute)))
                            {
                                MockNativeFunction(method);
                            }
                        }
                        else
                        {
                            if (method.IsDefined(typeof(NativeDllLoadedTriggerAttribute)))
                            {
                                RegisterTriggerMethod(method, ref _customLoadedTriggers, method.GetCustomAttribute <NativeDllLoadedTriggerAttribute>());
                            }

                            if (method.IsDefined(typeof(NativeDllBeforeUnloadTriggerAttribute)))
                            {
                                RegisterTriggerMethod(method, ref _customBeforeUnloadTriggers, method.GetCustomAttribute <NativeDllBeforeUnloadTriggerAttribute>());
                            }

                            if (method.IsDefined(typeof(NativeDllAfterUnloadTriggerAttribute)))
                            {
                                RegisterTriggerMethod(method, ref _customAfterUnloadTriggers, method.GetCustomAttribute <NativeDllAfterUnloadTriggerAttribute>());
                            }
                        }
                    }
                }
            }

            if (Options.loadingMode == DllLoadingMode.Preload)
            {
                LoadAll();
            }
        }