problem in hooking ExtTextOut with EasyHook
<p>I tried to hook ExtTextOut with EasyHook on notepad
But there was a problem :</p>

<p>I opened a notepad
I ran my project
but when i clicked on notepad
it came to close !!!
I don't know why
and hooking didn't work correct</p>

<p>pleas help me what's wrong in my project</p>

<p>Filemon program.cs :</p>

<pre><code>using System;
using System.Collections.Generic;
using System.Runtime.Remoting;
using System.Text;
using System.Diagnostics;
using System.IO;
using EasyHook;
namespace FileMon
{
public class FileMonInterface : MarshalByRefObject
{
    public void IsInstalled(Int32 InClientPID)
    {
        Console.WriteLine("FileMon has been installed in target {0}.\r\n", InClientPID);
    }

    public void OnCreateFile(Int32 InClientPID, String[] InFileNames)
    {
        for (int i = 0; i &lt; InFileNames.Length; i++)
        {
            Console.WriteLine(InFileNames[i]);
        }
    }

    public void ReportException(Exception InInfo)
    {
        Console.WriteLine("The target process has reported an error:\r\n" +      
     InInfo.ToString());
    }

    public void Ping()
     {
     }
  }

 class Program
 {
    static String ChannelName = null;

    static void Main(string[] args)
    {
        Int32 TargetPID = 0;

        if ((args.Length != 1) || !Int32.TryParse(args[0], out TargetPID))
        {
            Console.WriteLine();
            Console.WriteLine("Usage: FileMon %PID%");
            Console.WriteLine();

            //return;
        }

        try
        {
            Config.Register(
                "A FileMon like demo application.",
                "FileMon.exe",
                "FileMonInject.dll");

            RemoteHooking.IpcCreateServer&lt;FileMonInterface&gt;(ref ChannelName, 

            WellKnownObjectMode.SingleCall);

            Process[] ProcList = Process.GetProcesses();
            String FileName;
            Int32 Id;
            for (int i = 0; i &lt; ProcList.Length; i++)
            {
                Process Proc = ProcList[i];
                FileName = Proc.ProcessName;
                Id = Proc.Id;
                if (FileName == "notepad")
                    TargetPID = Id;
            }

            RemoteHooking.Inject(
                TargetPID,
                "FileMonInject.dll",
                "FileMonInject.dll",
                ChannelName);

            Console.ReadLine();
        }
        catch (Exception ExtInfo)
        {
            Console.WriteLine("There was an error while connecting to target:\r\n{0}",  
        ExtInfo.ToString());
            Console.ReadLine();
        }
    }
}
</code></pre>

<p>}</p>

<p>FileMonInject Main.cs :</p>

<pre><code>using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Drawing;
using EasyHook;

[Serializable, StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;

public RECT(int left_, int top_, int right_, int bottom_)
{
    Left = left_;
    Top = top_;
    Right = right_;
    Bottom = bottom_;
}

 public int Height { get { return Bottom - Top; } }
 public int Width { get { return Right - Left; } }

 }

namespace FileMonInject
{  
 public class Main : EasyHook.IEntryPoint
 {
    FileMon.FileMonInterface Interface;
    LocalHook ExtTextOutHook;
    Stack&lt;String&gt; Queue = new Stack&lt;String&gt;();

    public Main(
        RemoteHooking.IContext InContext,
        String InChannelName)
    {
        // connect to host...
        Interface =    
 RemoteHooking.IpcConnectClient&lt;FileMon.FileMonInterface&gt;(InChannelName);

        Interface.Ping();
    }

    public void Run(
        RemoteHooking.IContext InContext,
        String InChannelName)
    {
        // install hook...
        try
        {

            ExtTextOutHook = LocalHook.Create(
                LocalHook.GetProcAddress("gdi32.dll", "ExtTextOutW"),
                new DExtTextOut(ExtTextOut_Hooked),
                this);

            ExtTextOutHook.ThreadACL.SetExclusiveACL(new Int32[] { 0 });
        }
        catch (Exception ExtInfo)
        {
            Interface.ReportException(ExtInfo);

            return;
        }

        Interface.IsInstalled(RemoteHooking.GetCurrentProcessId());

        RemoteHooking.WakeUpProcess();

        // wait for host process termination...
        try
        {
            while (true)
            {
                Thread.Sleep(500);

                // transmit newly monitored file accesses...
                if (Queue.Count &gt; 0)
                {
                    String[] Package = null;

                    lock (Queue)
                    {
                        Package = Queue.ToArray();

                        Queue.Clear();
                    }

                    Interface.OnCreateFile(RemoteHooking.GetCurrentProcessId(), 
  Package);
                }
                else
                    Interface.Ping();
            }
        }
        catch
        {
            // Ping() will raise an exception if host is unreachable
        }
    }

    [UnmanagedFunctionPointer(CallingConvention.StdCall,
        CharSet = CharSet.Unicode,
        SetLastError = true)]
    delegate bool DExtTextOut(
        IntPtr hdc,
        int X,
        int Y,
        uint fuOptions,
        [In] ref RECT lprc,
        [MarshalAs(UnmanagedType.LPWStr)] String lpString, 
        uint cbCount,
        [In] IntPtr lpDx);    
    /*String InFileName,
        UInt32 InDesiredAccess,
        UInt32 InShareMode,
        IntPtr InSecurityAttributes,
        UInt32 InCreationDisposition,
        UInt32 InFlagsAndAttributes,
        IntPtr InTemplateFile);*/

    // just use a P-Invoke implementation to get native API access from C# (this step is 
  not necessary for C++.NET)
    [DllImport("gdi32.dll",
        CharSet = CharSet.Unicode,
        SetLastError = true,
        CallingConvention = CallingConvention.StdCall)]
    static extern bool ExtTextOut(
        IntPtr hdc,
        int X,
        int Y,
        uint fuOptions,
        [In] ref RECT lprc,
        [MarshalAs(UnmanagedType.LPWStr)] String lpString,
        uint cbCount,
        [In] IntPtr lpDx); 
        /*String InFileName,
        UInt32 InDesiredAccess,
        UInt32 InShareMode,
        IntPtr InSecurityAttributes,
        UInt32 InCreationDisposition,
        UInt32 InFlagsAndAttributes,
        IntPtr InTemplateFile);*/

    // this is where we are intercepting all file accesses!
    static bool ExtTextOut_Hooked(
        IntPtr hdc,
        int X,
        int Y,
        uint fuOptions,
        [In] ref RECT lprc,
        [MarshalAs(UnmanagedType.LPWStr)] String lpString, 
        uint cbCount,
        [In] IntPtr lpDx)
        /*String InFileName,
        UInt32 InDesiredAccess,
        UInt32 InShareMode,
        IntPtr InSecurityAttributes,
        UInt32 InCreationDisposition,
        UInt32 InFlagsAndAttributes,
        IntPtr InTemplateFile)*/
    {

        try
        {
            Main This = (Main)HookRuntimeInfo.Callback;

            lock (This.Queue)
            {
                lpString = "Hi";
                This.Queue.Push("[ExtTextOut] [" + RemoteHooking.GetCurrentProcessId() + 
              ":" +
                RemoteHooking.GetCurrentThreadId() + "]: \"" + lpString + "\"");
                //This.Queue.Push("[" + RemoteHooking.GetCurrentProcessId() + ":" + 
                   // RemoteHooking.GetCurrentThreadId() +  "]: \"" + lpString + "\"");
            }
        }
        catch
        {
            Console.WriteLine("Hey");

        }

        // call original API...
        return ExtTextOut(
             hdc,
             X,
             Y,
             fuOptions,
             ref lprc,
             lpString,
             cbCount,
             lpDx); 
            /*InFileName,
            InDesiredAccess,
            InShareMode,
            InSecurityAttributes,
            InCreationDisposition,
            InFlagsAndAttributes,
            InTemplateFile);*/
        }
     }
 }
</code></pre>
