C# Convertir IntPtr en int

Je suis dynamiquement l'appel de l'API Windows. J'ai trouvé un peu de code en ligne qui peut faire cela, et j'ai pris beaucoup d'intérêt pour elle. L'idée elle-même est génial pour dire le moins. Cependant, je n'arrive pas à faire fonctionner mon code. Les paramètres de la dynamique de l'appel sont de type string, string int[], et je voudrais utiliser l'API GetThreadContext avec les paramètres de pInfo.hThred et ref ctx (voir ci-dessous).

Appel d'API

GetThreadContext(pInfo.hThread, ref ctx);

Le code ci-dessus va faire un appel à la GetThreadContext API (étant donné qu'il est déclaré dans mon projet) et fonctionne parfaitement bien. La beauté de la dynamique de l'appel, cependant, est qu'aucune déclaration n'est nécessaire. Donc, ma tentative de la dynamique de l'appel:

ctx = new CONTEXT {ContextFlags = 0x10007};
PROCESS_INFORMATION pInfo;

CInvokeAPI.Invoke("kernel32","GetThreadContext",pInfo.hThread, ctx);

Ici, le problème est que je n'ai pas la moindre idée de comment je peux passer le paramètre ctx comme étant de type int, étant donné le fait que c'est une struct.

Veuillez voir ci-dessous pour plus de code

    [StructLayout(LayoutKind.Sequential)]
    struct CONTEXT
    {
        public uint ContextFlags;
        unsafe fixed byte unused[160];
        public uint Ebx;
        public uint Edx;
        public uint Ecx;
        public uint Eax;
        unsafe fixed byte unused2[24];
    }

    [StructLayout(LayoutKind.Sequential)]
    struct PROCESS_INFORMATION
    {
        public IntPtr hProcess;
        public IntPtr hThread;
        public int dwProcessId;
        public int dwThreadId;
    }

Appel de l'API Dynamiquement Classe

using System;
using System.Runtime.InteropServices;
using System.Text;
/* 
* Title: CInvokeAPI.cs
* Description: Call API by name implementation in purely managed C# (no 'unsafe' mess here).
* 
* Developed by: affixiate 
* Comments: If you use this code, I require you to give me credits. 
*/
public static class CInvokeAPI
{
///<summary>
///Generates a new, non-garbage collectable string in memory. Use this with Unicode "W" API.
///</summary>
///<param name="theString">A Unicode string.</param>
///<returns>Address of newly allocated string in memory. Remember to free it after use.</returns>
public static int StringToPtrW(string theString)
{
return StringToPtr(Encoding.Unicode.GetBytes(theString));
}
///<summary>
///Generates a new, non-garbage collectable string in memory. Use this with ANSI "A" API.
///</summary>
///<param name="theString">An ANSII string.</param>
///<returns>Address of newly allocated string in memory. Remember to free it after use.</returns>
public static int StringToPtrA(string theString)
{
return StringToPtr(Encoding.ASCII.GetBytes(theString));
}
///<summary>
///Internal method used to allocate memory.
///</summary>
///<param name="buf">A byte buffer.</param>
///<returns>Address of newly allocated memory. Remember to free it after use.</returns>
private static int StringToPtr(byte[] buf)
{
return (int)GCHandle.Alloc(buf, GCHandleType.Pinned).AddrOfPinnedObject();
}
///<summary>
///Invokes the specified Windows API.
///</summary>
///<param name="libraryName">Name of the library.</param>
///<param name="functionName">Name of the function.</param>
///<param name="args">The arguments.</param>
///<returns>True if function succeeds, otherwise false.</returns>
public static bool Invoke(string libraryName, string functionName, params int[] args)
{
/* Sanity checks. */
IntPtr hLoadLibrary = LoadLibrary(libraryName);
if (hLoadLibrary == IntPtr.Zero) return false;
IntPtr hGetProcAddress = GetProcAddress(hLoadLibrary, functionName);
if (hGetProcAddress == IntPtr.Zero) return false;
//Allocates more than enough  memory for an stdcall and the parameters of a WinAPI function
IntPtr hMemory = VirtualAlloc(IntPtr.Zero, 1024 * 1024, MEM_COMMIT | MEM_RESERVE, MEM_EXECUTE_READWRITE);
if (hMemory == IntPtr.Zero)
return false;
IntPtr hMemoryItr = hMemory;
//Prepends the stdcall header signature
Marshal.Copy(new byte[] {0x55, 0x89, 0xE5}, 0, hMemoryItr, 0x3);
hMemoryItr = (IntPtr)((int)hMemoryItr + 0x3);
//Loop through the passed in arguments and place them on the stack in reverse order
for (int i = (args.Length - 1); i >= 0; i--) 
{
Marshal.Copy(new byte[] {0x68}, 0, hMemoryItr, 0x1); 
hMemoryItr = (IntPtr)((int)hMemoryItr + 0x1);
Marshal.Copy(BitConverter.GetBytes(args[i]), 0, hMemoryItr, 0x4);
hMemoryItr = (IntPtr)((int)hMemoryItr + 0x4);
}
Marshal.Copy(new byte[] {0xE8}, 0, hMemoryItr, 0x1);
hMemoryItr = (IntPtr)((int)hMemoryItr + 0x1);
Marshal.Copy(BitConverter.GetBytes((int)hGetProcAddress - (int)hMemoryItr - 0x4), 0, hMemoryItr, 0x4);
hMemoryItr = (IntPtr)((int)hMemoryItr + 0x4);
//Cleaning up the stack
Marshal.Copy(new byte[] {0x5D, 0xC2, 0x4, 0x0 /* <= I made a LOL. */}, 0, hMemoryItr, 0x4);
//Don't forget to increment if you are adding more ASM code here: hMemoryItr = (IntPtr)((int)hMemoryItr + 0x4);
try
{
var executeAsm = (RunAsm) Marshal.GetDelegateForFunctionPointer(hMemory, typeof (RunAsm));
executeAsm();
}
catch { return false; }
//Clean up the memory we allocated to do the dirty work
VirtualFree(hMemory, 0, MEM_RELEASE);
return true;
}
//ReSharper disable InconsistentNaming
private const uint MEM_RELEASE = 0x8000;
private const uint MEM_COMMIT = 0x1000;
private const uint MEM_RESERVE = 0x2000;
private const uint MEM_EXECUTE_READWRITE = 0x40;
//ReSharper restore InconsistentNaming
//My own sexy delegate:
[UnmanagedFunctionPointer(CallingConvention.StdCall, SetLastError = true)]
private delegate void RunAsm();
//WinAPI used:
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool VirtualFree(IntPtr lpAddress, UInt32 dwSize, uint dwFreeType);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr VirtualAlloc(IntPtr lpAddress, UInt32 dwSize, uint flAllocationType, uint flProtect);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr LoadLibrary(string lpFileName);
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Ansi)]
private static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
}
Pourriez-vous fournir les paramètres attendus par myVoid sur la non géré side ? est-il vraiment d'une POIGNÉE et d'un CONTEXTE* ? Si oui, vous aurez besoin d'allouer de la mémoire non gérée, pour cela, une copie d'une instance de CONTEXTE à l'intérieur, voir msdn.microsoft.com/en-us/library/... si au lieu d'une poignée vous avez besoin d'un PROCESS_INFORMATION* vous devez faire la même chose pour ce paramètre.
Mis à jour ...
Méfiez-vous des 64-bit
En utilisant 32 bits de la machine. Je vous remercie bien.

OriginalL'auteur | 2011-08-03