[Code] PInvoke with Type Constraints menu

User Tag List

Results 1 to 7 of 7
  1. #1
    bigtimt's Avatar Active Member
    Reputation
    41
    Join Date
    Mar 2008
    Posts
    100
    Thanks G/R
    2/4
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    [Code] PInvoke with Type Constraints

    Here is an example of RtlMoveMemory with type constraints. This can be applied to other functions such as ReadProcessMemory. Enjoy! No comments because the code should explain itself. Let me know if you have any questions.

    Code:
        public static class NativeMethods
        {
            [DllImport("Kernel32", EntryPoint = "GetModuleHandleA")]
            public static extern IntPtr GetModuleHandle(string moduleName);
    
            [DllImport("Kernel32")]
            public static extern IntPtr GetProcAddress(IntPtr moduleHandle, string procedureName);
        }
    
        static class MemoryFunctions<T> where T : struct
        {
            internal delegate void WriteArrayDelegate(IntPtr pDest, T[] pSrc, int size);
            internal delegate void ReadValueDelegate(ref T pDest, IntPtr pSrc, int size);
            internal delegate void ReadArrayDelegate(T[] pDest, IntPtr pSrc, int size);
    
            internal static WriteArrayDelegate WriteArray;
            internal static ReadValueDelegate ReadValue;
            internal static ReadArrayDelegate ReadArray;
    
            internal static int Size { get; } = Marshal.SizeOf<T>();
    
            static MemoryFunctions()
            {
                var hKernel32 = NativeMethods.GetModuleHandle("Kernel32");
                var pRtlMoveMemory = NativeMethods.GetProcAddress(hKernel32, "RtlMoveMemory");
                var GetDelegate = typeof(Marshal).GetMethod("GetDelegateForFunctionPointerInternal", BindingFlags.Static | BindingFlags.NonPublic);
    
                WriteArray = GetDelegate.Invoke(null, new object[] { pRtlMoveMemory, typeof(WriteArrayDelegate) }) as WriteArrayDelegate;
                ReadValue = GetDelegate.Invoke(null, new object[] { pRtlMoveMemory, typeof(ReadValueDelegate) }) as ReadValueDelegate;
                ReadArray = GetDelegate.Invoke(null, new object[] { pRtlMoveMemory, typeof(ReadArrayDelegate) }) as ReadArrayDelegate;
            }
        }
    
        public static class LocalMemory
        {
            public static T Read<T>(IntPtr ptr) where T : struct
            {
                var result = default(T);
    
                MemoryFunctions<T>.ReadValue(ref result, ptr, MemoryFunctions<T>.Size);
    
                return result;
            }
    
            public static void Read<T>(IntPtr ptr, out T result) where T : struct
            {
                result = default(T);
    
                MemoryFunctions<T>.ReadValue(ref result, ptr, MemoryFunctions<T>.Size);
            }
    
            public static T[] Read<T>(IntPtr ptr, int length) where T : struct
            {
                var result = new T[length];
    
                MemoryFunctions<T>.ReadArray(result, ptr, MemoryFunctions<T>.Size * length);
    
                return result;
            }
    
            public static void Write<T>(IntPtr ptr, params T[] values) where T : struct
            {
                MemoryFunctions<T>.WriteArray(ptr, values, MemoryFunctions<T>.Size * values.Length);
            }
        }
    Last edited by bigtimt; 04-12-2017 at 08:21 AM.

    [Code] PInvoke with Type Constraints
  2. #2
    lolp1's Avatar Site Donator CoreCoins Purchaser
    Reputation
    190
    Join Date
    Feb 2013
    Posts
    210
    Thanks G/R
    43/77
    Trade Feedback
    3 (100%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    This should be enough for most people, you need to do a little bit more if external.
    Code:
        internal class UnsafeNativeMethods {
            [DllImport("kernel32.dll", EntryPoint = "CopyMemory", SetLastError = false)]
            [SecurityCritical]
            internal static extern void CopyMemory(IntPtr dest, IntPtr src, uint count);
     
            [DllImport("kernel32.dll", EntryPoint = "CopyMemory", SetLastError = false)]
            [SecurityCritical]
            internal static extern unsafe void CopyMemoryPtr(void* dest, void* src, uint count);
        }
     
        [SuppressMessage("ReSharper", "StaticMemberInGenericType")]
        public static class FastStruct<T> where T : struct {
            private static readonly GetPtrDelegate GetPtr = BuildGetPtrMethod();
            private static readonly PtrToStructureDelegateIntPtr PtrToStructureIntPtr = BuildLoadFromIntPtrMethod();
            private static readonly unsafe PtrToStructureDelegateBytePtr PtrToStructureBytePtr = BuildLoadFromBytePtrMethod();
     
            public static readonly int Size = Marshal.SizeOf<T>();
     
            private static DynamicMethod _methodGetPtr;
            private static DynamicMethod _methodLoadIntPtr;
            private static DynamicMethod _methodLoadBytePtr;
     
            private static GetPtrDelegate BuildGetPtrMethod() {
                _methodGetPtr = new DynamicMethod("GetStructPtr<" + typeof(T).FullName + ">",
                    typeof(IntPtr), new[] {typeof(T).MakeByRefType()}, typeof(FastStruct<T>));
     
                var generator = _methodGetPtr.GetILGenerator();
                generator.Emit(OpCodes.Ldarg_0);
                generator.Emit(OpCodes.Conv_U);
                generator.Emit(OpCodes.Ret);
                return (GetPtrDelegate) _methodGetPtr.CreateDelegate(typeof(GetPtrDelegate));
            }
     
            private static PtrToStructureDelegateIntPtr BuildLoadFromIntPtrMethod() {
                _methodLoadIntPtr = new DynamicMethod("PtrToStructureIntPtr<" + typeof(T).FullName + ">",
                    typeof(T), new[] {typeof(IntPtr)}, typeof(FastStruct<T>));
     
                var generator = _methodLoadIntPtr.GetILGenerator();
                generator.Emit(OpCodes.Ldarg_0);
                generator.Emit(OpCodes.Ldobj, typeof(T));
                generator.Emit(OpCodes.Ret);
     
                return (PtrToStructureDelegateIntPtr) _methodLoadIntPtr.CreateDelegate(typeof(PtrToStructureDelegateIntPtr));
            }
     
            private static PtrToStructureDelegateBytePtr BuildLoadFromBytePtrMethod() {
                _methodLoadBytePtr = new DynamicMethod("PtrToStructureBytePtr<" + typeof(T).FullName + ">",
                    typeof(T), new[] {typeof(byte*)}, typeof(FastStruct<T>));
     
                var generator = _methodLoadBytePtr.GetILGenerator();
                generator.Emit(OpCodes.Ldarg_0);
                generator.Emit(OpCodes.Ldobj, typeof(T));
                generator.Emit(OpCodes.Ret);
     
                return (PtrToStructureDelegateBytePtr) _methodLoadBytePtr.CreateDelegate(typeof(PtrToStructureDelegateBytePtr));
            }
     
            public static T PtrToStructure(IntPtr ptr) => PtrToStructureIntPtr(ptr);
     
            public static unsafe T PtrToStructure(byte* ptr) => PtrToStructureBytePtr(ptr);
     
            public static T[] ReadArray(IntPtr source, int bytesCount) {
                var elementSize = (uint) Size;
     
                var buffer = new T[bytesCount / elementSize];
     
                if (bytesCount <= 0)
                    return buffer;
                var intPtr = GetPtr(ref buffer[0]);
                UnsafeNativeMethods.CopyMemory(intPtr, source, (uint) bytesCount);
     
                return buffer;
            }
     
            private delegate IntPtr GetPtrDelegate(ref T value);
     
            private delegate T PtrToStructureDelegateIntPtr(IntPtr pointer);
     
            private unsafe delegate T PtrToStructureDelegateBytePtr(byte* pointer);
        }

  3. #3
    bigtimt's Avatar Active Member
    Reputation
    41
    Join Date
    Mar 2008
    Posts
    100
    Thanks G/R
    2/4
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    AFAIK, the only issue with using your method is that it will only work on public types. Any types that you want to keep private or internal either have to be in the same assembly or changed to public.

    Could be wrong but that's what I ran into at some point.

    This is the way I've found to not PInvoke and also not use DynamicMethod:

    Code:
                public static T ReadValue<T>(IntPtr ptr, int ofs = 0) where T : struct
                {
                    var buffer = default(T);
                    var pBuffer = __makeref(buffer);
    
                    *((IntPtr*)&pBuffer) = ptr + ofs;
    
                    try
                    {
                        return __refvalue(pBuffer, T);
                    }
                    catch (NullReferenceException)
                    {
                        return buffer;
                    }
                }
    
                public static bool WriteValue<T>(T value, IntPtr ptr, int ofs = 0) where T : struct
                {
                    var buffer = default(T);
                    var pBuffer = __makeref(buffer);
         
                    *((IntPtr*)&pBuffer) = ptr + ofs;
    
                    try
                    {
                        __refvalue(pBuffer, T) = value;
                        return true;
                    }
                    catch (NullReferenceException) { return false; }
                }
    Last edited by bigtimt; 04-12-2017 at 08:57 AM.

  4. Thanks Jadd, lolp1, tutrakan (3 members gave Thanks to bigtimt for this useful post)
  5. #4
    Jadd's Avatar 🐸
    Reputation
    1515
    Join Date
    May 2008
    Posts
    2,433
    Thanks G/R
    81/336
    Trade Feedback
    1 (100%)
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Use RtlCopyMemory. It's faster. You won't have any problems with it unless you're doing something you shouldn't be.

    Also, no VirtualProtect?

  6. #5
    bigtimt's Avatar Active Member
    Reputation
    41
    Join Date
    Mar 2008
    Posts
    100
    Thanks G/R
    2/4
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Code was just an example for people to incorporate into their own libs, it wasn't meant to be a full class. The __makeref and __ref value methods are actually twice as fast as RtlMoveMemory according to my benchmarking over 1mil tests.
    Last edited by bigtimt; 04-12-2017 at 11:51 AM.

  7. Thanks Jadd (1 members gave Thanks to bigtimt for this useful post)
  8. #6
    Jadd's Avatar 🐸
    Reputation
    1515
    Join Date
    May 2008
    Posts
    2,433
    Thanks G/R
    81/336
    Trade Feedback
    1 (100%)
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by bigtimt View Post
    Code was just an example for people to incorporate into their own libs, it wasn't meant to be a full class. The __makeref and __ref value methods are actually twice as fast as RtlMoveMemory according to my benchmarking over 1mil tests.
    As expected. +1 for using undocumented keywords/functions.

  9. Thanks bigtimt (1 members gave Thanks to Jadd for this useful post)
  10. #7
    MaiN's Avatar Elite User
    Reputation
    335
    Join Date
    Sep 2006
    Posts
    1,047
    Thanks G/R
    0/10
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    By far the fastest way is with System.Runtime.CompilerServices.Unsafe: NuGet Gallery
    | System.Runtime.CompilerServices.Unsafe 4.3.0
    .

    Install this and use Unsafe.Read<T>/Write<T> for single value reads and Unsafe.CopyBlock<T> for arrays.
    It should match or be faster than any __refvalue hacks, and it will also work on .NET standard.
    [16:15:41] Cypher: caus the CPU is a dick
    [16:16:07] kynox: CPU is mad
    [16:16:15] Cypher: CPU is all like
    [16:16:16] Cypher: whatever, i do what i want

  11. Thanks Jadd (1 members gave Thanks to MaiN for this useful post)

Similar Threads

  1. Finding Wallclimb codes etc. with Cheat Engine?
    By kaiverrettu in forum WoW Bots Questions & Requests
    Replies: 2
    Last Post: 11-23-2010, 01:43 AM
  2. [Game] Type your name with your elbow!
    By Illidan_000 in forum Community Chat
    Replies: 83
    Last Post: 08-05-2010, 06:42 AM
  3. What happens when you type with your nose?
    By aberfnull in forum Community Chat
    Replies: 6
    Last Post: 11-10-2007, 03:51 AM
  4. [Request] Itemlist with codes.
    By TforTyranth in forum WoW ME Questions and Requests
    Replies: 2
    Last Post: 10-03-2007, 08:12 AM
  5. Auto-Queue/Anti-AFK HonorBot With Source Code (c++)
    By Flying Piggy in forum World of Warcraft Bots and Programs
    Replies: 12
    Last Post: 09-12-2007, 11:13 AM
All times are GMT -5. The time now is 05:13 PM. Powered by vBulletin® Version 4.2.3
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved. User Alert System provided by Advanced User Tagging (Pro) - vBulletin Mods & Addons Copyright © 2025 DragonByte Technologies Ltd.
Google Authenticator verification provided by Two-Factor Authentication (Free) - vBulletin Mods & Addons Copyright © 2025 DragonByte Technologies Ltd.
Digital Point modules: Sphinx-based search