コード例 #1
0
ファイル: NativeDetour.cs プロジェクト: ezdiy/MonoMod
        public NativeDetour(MethodBase method, IntPtr from, IntPtr to)
        {
            Data   = DetourManager.Native.Create(from, to);
            Method = method;

            // Backing up the original function only needs to happen once.
            if (Method != null && Method.GetMethodBody() != null)
            {
                _BackupMethod = method.CreateILCopy();
            }

            // BackupNative is required even if BackupMethod is present to undo the detour.
            _BackupNative = DetourManager.Native.MemAlloc(Data.Size);
            DetourManager.Native.Copy(Data.Method, _BackupNative, Data.Size);

            Apply();
        }
コード例 #2
0
        internal HookEndpoint(MethodBase method)
        {
            Method = method;

            // Add a "transparent" detour for IL manipulation.

            bool hasMethodBody;

            try {
                hasMethodBody = (method.GetMethodBody()?.GetILAsByteArray()?.Length ?? 0) != 0;
            } catch {
                hasMethodBody = false;
            }

            if (hasMethodBody)
            {
                // Note: This can but shouldn't fail, mainly if the user hasn't provided a Cecil ModuleDefinition generator.
                DMD      = new DynamicMethodDefinition(method, HookEndpointManager.GenerateCecilModule);
                ILCopy   = method.CreateILCopy();
                ILDetour = new Detour(method, ILCopy);
                DetourILDetourTarget();
            }
        }
コード例 #3
0
        public NativeDetour(MethodBase method, IntPtr from, IntPtr to)
        {
            Data   = DetourManager.Native.Create(from, to);
            Method = method;

            // Backing up the original function only needs to happen once.
            MethodBody body;

            try {
                body = Method?.GetMethodBody();
            } catch (InvalidOperationException) {
                body = null;
            }
            if (body != null)
            {
                _BackupMethod = method.CreateILCopy();
            }

            // BackupNative is required even if BackupMethod is present to undo the detour.
            _BackupNative = DetourManager.Native.MemAlloc(Data.Size);
            DetourManager.Native.Copy(Data.Method, _BackupNative, Data.Size);

            Apply();
        }
コード例 #4
0
        public Detour(MethodBase from, MethodBase to)
        {
            Method = from;
            Target = to;

            // TODO: Check target method arguments.

            if (!_BackupMethods.ContainsKey(Method))
            {
                _BackupMethods[Method] = Method.CreateILCopy();
            }

            // Generate a "chained trampoline" DynamicMethod.
            ParameterInfo[] args = Method.GetParameters();
            Type[]          argTypes;
            if (!Method.IsStatic)
            {
                argTypes    = new Type[args.Length + 1];
                argTypes[0] = Method.DeclaringType;
                for (int i = 0; i < args.Length; i++)
                {
                    argTypes[i + 1] = args[i].ParameterType;
                }
            }
            else
            {
                argTypes = new Type[args.Length];
                for (int i = 0; i < args.Length; i++)
                {
                    argTypes[i] = args[i].ParameterType;
                }
            }

            _ChainedTrampoline = new DynamicMethod(
                $"chain_{Method.Name}_{GetHashCode()}",
                (Method as MethodInfo)?.ReturnType ?? typeof(void), argTypes,
                Method.DeclaringType,
                false // Otherwise just ret is invalid for whatever reason.
                ).StubCriticalDetour().Pin();

            // Add the detour to the detour map.
            List <Detour> detours;

            lock (_DetourMap) {
                if (!_DetourMap.TryGetValue(Method, out detours))
                {
                    _DetourMap[Method] = detours = new List <Detour>();
                }
            }
            lock (detours) {
                // New Detour instances are always on the top.
                if (detours.Count > 0)
                {
                    detours[detours.Count - 1]._TopUndo();
                }
                _TopApply();

                // Do the initial "chained trampoline" setup.
                NativeDetourData link;
                if (detours.Count > 0)
                {
                    // If a previous Detour exists in the chain, detour our "chained trampoline" to it,
                    link = DetourManager.Native.Create(
                        _ChainedTrampoline.GetNativeStart(),
                        detours[detours.Count - 1].Target.GetNativeStart()
                        );
                }
                else
                {
                    // If this is the first Detour in the chain, detour our "chained trampoline" to the original method.
                    link = DetourManager.Native.Create(
                        _ChainedTrampoline.GetNativeStart(),
                        _BackupMethods[Method].GetNativeStart()
                        );
                }
                DetourManager.Native.MakeWritable(link);
                DetourManager.Native.Apply(link);
                DetourManager.Native.MakeExecutable(link);
                DetourManager.Native.Free(link);

                detours.Add(this);
            }
        }