【お知らせ】プログラミング記事の投稿はQiitaに移行しました。

C#でJITからコールバック

C#JITからコールバックさせてみました。PythonのコードC#に移植したものです。

using System;
using System.Runtime.InteropServices;

class Program
{
    [DllImport("kernel32.dll", SetLastError = true)]
    static extern IntPtr VirtualAlloc(IntPtr lpAddress, int dwSize,
        int flAllocationType, int flProtect);

    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool VirtualFree(IntPtr lpAddress, int dwSize,
        int dwFreeType);

    const int MEM_COMMIT = 0x1000;
    const int MEM_RELEASE = 0x8000;
    const int PAGE_EXECUTE_READWRITE = 0x40;

    static byte[] codes =
    {
        0x6a, 0x41,             // push 65
        0xff, 0x54, 0x24, 0x08, // call [esp+8]
        0x83, 0xc4, 0x04,       // add esp, 4
        0xc3,                   // ret
    };

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    delegate void Delg1(int a);

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    delegate void Delg2(Delg1 a);

    static void Main(string[] args)
    {
        var buflen = codes.Length;
        var p = VirtualAlloc(IntPtr.Zero, buflen,
            MEM_COMMIT, PAGE_EXECUTE_READWRITE);
        Marshal.Copy(codes, 0, p, buflen);

        var f = Marshal.GetDelegateForFunctionPointer(
            p, typeof(Delg2)) as Delg2;
        f(ch => Console.Write("{0}", (char)ch));

        VirtualFree(p, 0, MEM_RELEASE);
    }
}