Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

add missing EasyHook libraries

  • Loading branch information...
commit 019486965acf1e3ff43dd8c203855c9b236f745d 1 parent 6926b36
Eike Siewertsen authored August 20, 2012
1,381  EasyHook/EasyHook.XML
... ...
@@ -0,0 +1,1381 @@
  1
+<?xml version="1.0"?>
  2
+<doc>
  3
+    <assembly>
  4
+        <name>EasyHook</name>
  5
+    </assembly>
  6
+    <members>
  7
+        <member name="T:EasyHook.RemoteHooking.IContext">
  8
+            <summary>
  9
+            A context contains some basic information about the environment
  10
+            in which your library main method has been invoked. You will always
  11
+            get an instance of this interface in your library <c>Run</c> method
  12
+            and your library <c>Initialize</c> method. 
  13
+            </summary>
  14
+        </member>
  15
+        <member name="T:EasyHook.RemoteHooking">
  16
+            <summary>
  17
+            Provides all things related to library injection, inter-process-communication (IPC) and
  18
+            helper routines for common remote tasks.
  19
+            </summary>
  20
+            <remarks>
  21
+  The following demonstrates how to use <see cref="T:EasyHook.RemoteHooking"/> and <see cref="T:EasyHook.Config"/>:
  22
+  <code>
  23
+    using System;
  24
+    using System.Collections.Generic;
  25
+    using System.Runtime.Remoting;
  26
+    using System.Text;
  27
+    using System.IO;
  28
+    using EasyHook;
  29
+
  30
+    namespace FileMon
  31
+    {
  32
+        public class FileMonInterface : MarshalByRefObject
  33
+        {
  34
+            public void IsInstalled(Int32 InClientPID)
  35
+            {
  36
+                Console.WriteLine("FileMon has been installed in target {0}.\r\n", InClientPID);
  37
+            }
  38
+
  39
+            public void OnCreateFile(Int32 InClientPID, String[] InFileNames)
  40
+            {
  41
+                for (int i = 0; i &lt; InFileNames.Length; i++)
  42
+                {
  43
+                    Console.WriteLine(InFileNames[i]);
  44
+                }
  45
+            }
  46
+
  47
+            public void ReportException(Exception InInfo)
  48
+            {
  49
+                Console.WriteLine("The target process has reported an error:\r\n" + InInfo.ToString());
  50
+            }
  51
+
  52
+            public void Ping()
  53
+            {
  54
+            }
  55
+        }
  56
+
  57
+        class Program
  58
+        {
  59
+            static String ChannelName = null;
  60
+
  61
+            static void Main(string[] args)
  62
+            {
  63
+                try
  64
+                {
  65
+                    Config.Register(
  66
+                        "A FileMon like demo application.",
  67
+                        "FileMon.exe",
  68
+                        "FileMonInject.dll");
  69
+
  70
+                    RemoteHooking.IpcCreateServer&lt;FileMonInterface&gt;(ref ChannelName, WellKnownObjectMode.SingleCall);
  71
+
  72
+                    RemoteHooking.Inject(
  73
+                        Int32.Parse(args[0]),
  74
+                        "FileMonInject.dll",
  75
+                        "FileMonInject.dll",
  76
+                        ChannelName);
  77
+                
  78
+                    Console.ReadLine();
  79
+                }
  80
+                catch (Exception ExtInfo)
  81
+                {
  82
+                    Console.WriteLine("There was an error while connecting to target:\r\n{0}", ExtInfo.ToString());
  83
+                }
  84
+            }
  85
+        }
  86
+    }
  87
+  </code>
  88
+</remarks>
  89
+        </member>
  90
+        <member name="M:EasyHook.RemoteHooking.WakeUpProcess">
  91
+            <summary>
  92
+            If the library was injected with <see cref="M:EasyHook.RemoteHooking.CreateAndInject(System.String,System.String,System.Int32,System.String,System.String,System.Int32@,System.Object[])"/>, this will
  93
+            finally start the current process. You should call this method in the library
  94
+            <c>Run()</c> method after all hooks have been installed.
  95
+            </summary>
  96
+        </member>
  97
+        <member name="M:EasyHook.RemoteHooking.IpcCreateServer``1(System.String@,System.Runtime.Remoting.WellKnownObjectMode,System.Security.Principal.WellKnownSidType[])">
  98
+            <summary>
  99
+            Creates a globally reachable, managed IPC-Port.
  100
+            </summary>
  101
+            <remarks>
  102
+            Because it is something tricky to get a port working for any constellation of
  103
+            target processes, I decided to write a proper wrapper method. Just keep the returned
  104
+            <see cref="T:System.Runtime.Remoting.Channels.Ipc.IpcChannel"/> alive, by adding it to a global list or static variable,
  105
+            as long as you want to have the IPC port open.
  106
+            </remarks>
  107
+            <typeparam name="TRemoteObject">
  108
+            A class derived from <see cref="T:System.MarshalByRefObject"/> which provides the
  109
+            method implementations this server should expose.
  110
+            </typeparam>
  111
+            <param name="InObjectMode">
  112
+            <see cref="F:System.Runtime.Remoting.WellKnownObjectMode.SingleCall"/> if you want to handle each call in an new
  113
+            object instance, <see cref="F:System.Runtime.Remoting.WellKnownObjectMode.Singleton"/> otherwise. The latter will implicitly
  114
+            allow you to use "static" remote variables.
  115
+            </param>
  116
+            <param name="RefChannelName">
  117
+            Either <c>null</c> to let the method generate a random channel name to be passed to 
  118
+            <see cref="M:EasyHook.RemoteHooking.IpcConnectClient``1(System.String)"/> or a predefined one. If you pass a value unequal to 
  119
+            <c>null</c>, you shall also specify all SIDs that are allowed to connect to your channel!
  120
+            </param>
  121
+            <param name="InAllowedClientSIDs">
  122
+            If no SID is specified, all authenticated users will be allowed to access the server
  123
+            channel by default. You must specify an SID if <paramref name="RefChannelName"/> is unequal to <c>null</c>.
  124
+            </param>
  125
+            <returns>
  126
+            An <see cref="T:System.Runtime.Remoting.Channels.Ipc.IpcChannel"/> that shall be keept alive until the server is not needed anymore.
  127
+            </returns>
  128
+            <exception cref="T:System.Security.HostProtectionException">
  129
+            If a predefined channel name is being used, you are required to specify a list of well known SIDs
  130
+            which are allowed to access the newly created server.
  131
+            </exception>
  132
+            <exception cref="T:System.Runtime.Remoting.RemotingException">
  133
+            The given channel name is already in use.
  134
+            </exception>
  135
+        </member>
  136
+        <member name="M:EasyHook.RemoteHooking.IpcConnectClient``1(System.String)">
  137
+            <summary>
  138
+            Connects to a globally reachable, managed IPC port.
  139
+            </summary>
  140
+            <remarks>
  141
+            All requests have to be made through the returned object instance.
  142
+            Please note that even if you might think that managed IPC is quiet slow,
  143
+            this is not usually the case. Internally a mechanism is being used to
  144
+            directly continue execution within the server process, so that even if 
  145
+            your thread does nothing while dispatching the request, no CPU time is lost,
  146
+            because the server thread seemlessly takes over exection. And to be true,
  147
+            the rare conditions in which you will need high-speed IPC ports are not
  148
+            worth the effort to break with NET's exciting IPC capabilities. In times
  149
+            of Quad-Cores, managed marshalling isn't that slow anymore.
  150
+            </remarks>
  151
+            <typeparam name="TRemoteObject">
  152
+            An object derived from <see cref="T:System.MarshalByRefObject"/> which provides the
  153
+            method implementations this server should provide. Note that only calls through the
  154
+            returned object instance will be redirected to the server process! ATTENTION: Static fields
  155
+            and members are always processed locally only...
  156
+            </typeparam>
  157
+            <param name="InChannelName">
  158
+            The name of the channel to connect to, usually obtained with <see cref="M:EasyHook.RemoteHooking.IpcCreateServer``1(System.String@,System.Runtime.Remoting.WellKnownObjectMode,System.Security.Principal.WellKnownSidType[])"/>.
  159
+            </param>
  160
+            <returns>
  161
+            An remote object instance which member accesses will be redirected to the server.
  162
+            </returns>
  163
+            <exception cref="T:System.ArgumentException">
  164
+            Unable to create remote object or invalid channel name...
  165
+            </exception>
  166
+        </member>
  167
+        <member name="M:EasyHook.RemoteHooking.Inject(System.Int32,EasyHook.InjectionOptions,System.String,System.String,System.Object[])">
  168
+            <summary>
  169
+            Injects the given user library into the target process. No memory leaks are left
  170
+            in the target, even if injection fails for unknown reasons. 
  171
+            </summary>
  172
+            <remarks>
  173
+            <para>
  174
+            There are two possible user library paths. The first one should map to
  175
+            a 32-bit library, and the second one should map to 64-bit library. If your
  176
+            code has been compiled for "AnyCPU", like it's the default for C#, you may
  177
+            even specify one library path for both parameters. Please note that your
  178
+            library including all of it's dependencies must be registered in the
  179
+            Global Assembly Cache (GAC). Refer to <see cref="M:EasyHook.Config.Register(System.String,System.String[])"/> for more
  180
+            information about how to get them there.
  181
+            </para><para>
  182
+            If you inject a library into any target process please keep in mind that
  183
+            your working directory will be switched. EasyHook will automatically add
  184
+            the directory of the injecting application as first directory of the target's PATH environment
  185
+            variable. So make sure that all required dependencies are either located
  186
+            within the injecting application's directory, a system directory or any directory defaultly
  187
+            contained in the PATH variable. As all managed assemblies have to be in the GAC
  188
+            there is no need for them being in any of those directories!
  189
+            </para> <para>
  190
+            EasyHook provides extensive error information during injection. Any kind of failure is
  191
+            being catched and thrown as an exception by this method. If for example your library
  192
+            does not expose a class implementing <see cref="T:EasyHook.IEntryPoint"/>, an exception will be
  193
+            raised in the target process during injection. The exception will be redirected to this method
  194
+            and you can catch it in a try-catch statement around <see cref="M:EasyHook.RemoteHooking.Inject(System.Int32,EasyHook.InjectionOptions,System.String,System.String,System.Object[])"/>.
  195
+            </para> <para>
  196
+            You will often have to pass parameters to your injected library. <see cref="T:System.Runtime.Remoting.Channels.Ipc.IpcChannel"/> 
  197
+            names are common, but also any other kind of data can be passed. You may add a custom list
  198
+            of objects marked with the <see cref="T:System.SerializableAttribute"/>. All common NET classes
  199
+            will be serializable by default, but if you are using your own classes you might have to provide
  200
+            serialization by yourself. The custom parameter list will be passed unchanged to your injected
  201
+            library entry points <c>Run</c> and <c>Initialize</c>. Verify that all required type libraries to deserialize
  202
+            your parameter list are in the GAC.
  203
+            </para><para>
  204
+            It is supported to inject code into 64-bit processes from within 32-bit processes and
  205
+            vice versa. It is also supported to inject code into other terminal sessions. Of course
  206
+            this will require additional processes and services to be created, but as they are managed
  207
+            internally, you won't notice them! There will be some delays when injecting the first library.
  208
+            Further injections are completed much faster!
  209
+            </para><para>
  210
+            Even if it would technically be possible to inject a library for debugging purposes into
  211
+            the current process, it will throw an exception. This is because it heavily depends on
  212
+            your injected library whether the current process will be damaged. Any kind of communication
  213
+            may lead into deadlocks if you hook the wrong APIs. Just use the capability of Visual Studio
  214
+            to debug more than one process simultanously which will allow you to debug your library
  215
+            as if it would be injected into the current process without running into any side-effects.
  216
+            </para>
  217
+            <para>
  218
+            The given exceptions are those which are thrown by EasyHook code. The NET framework might throw
  219
+            any other exception not listed here. Don't rely on the exception type. If you passed valid parameters,
  220
+            the only exceptions you should explicitly check for are <see cref="T:System.NotSupportedException"/> and
  221
+            <see cref="T:System.AccessViolationException"/>. All others
  222
+            shall be catched together and threaded as bad environment or invalid parameter error.
  223
+            </para>
  224
+            </remarks>
  225
+            <param name="InTargetPID">
  226
+            The target process ID.
  227
+            </param>
  228
+            <param name="InOptions">
  229
+            A valid combination of options.
  230
+            </param>
  231
+            <param name="InLibraryPath_x86">
  232
+            A partially qualified assembly name or a relative/absolute file path of the 32-bit version of your library. 
  233
+            For example "MyAssembly, PublicKeyToken=248973975895496" or ".\Assemblies\\MyAssembly.dll". 
  234
+            </param>
  235
+            <param name="InLibraryPath_x64">
  236
+            A partially qualified assembly name or a relative/absolute file path of the 64-bit version of your library. 
  237
+            For example "MyAssembly, PublicKeyToken=248973975895496" or ".\Assemblies\\MyAssembly.dll". 
  238
+            </param>
  239
+            <param name="InPassThruArgs">
  240
+            A serializable list of parameters being passed to your library entry points <c>Run()</c> and
  241
+            <c>Initialize()</c>.
  242
+            </param>
  243
+            <exception cref="T:System.InvalidOperationException">
  244
+            It is unstable to inject libraries into the same process. This exception is disabled in DEBUG mode.
  245
+            </exception>
  246
+            <exception cref="T:System.AccessViolationException">
  247
+            Access to target process denied or the current user is not an administrator.
  248
+            </exception>
  249
+            <exception cref="T:System.ArgumentException">
  250
+            The given process does not exist or unable to serialize/deserialize one or more pass thru arguments.
  251
+            </exception>
  252
+            <exception cref="T:System.IO.FileNotFoundException">
  253
+            The given user library could not be found.
  254
+            </exception>
  255
+            <exception cref="T:System.OutOfMemoryException">
  256
+            Unable to allocate unmanaged memory in current or target process.
  257
+            </exception>
  258
+            <exception cref="T:System.NotSupportedException">
  259
+            It is not supported to inject into the target process. This is common on Windows Vista and Server 2008.
  260
+            </exception>
  261
+            <exception cref="T:System.TimeoutException">
  262
+            Unable to wait for user library to be initialized. Check your library <c>Initialize()</c> handler.
  263
+            </exception>
  264
+            <exception cref="T:System.EntryPointNotFoundException">
  265
+            The given user library does not export a class implementing the <see cref="T:EasyHook.IEntryPoint"/> interface.
  266
+            </exception>
  267
+        </member>
  268
+        <member name="M:EasyHook.RemoteHooking.Inject(System.Int32,System.String,System.String,System.Object[])">
  269
+            <summary>
  270
+            See <see cref="M:EasyHook.RemoteHooking.Inject(System.Int32,EasyHook.InjectionOptions,System.String,System.String,System.Object[])"/> for more information.
  271
+            </summary>
  272
+            <param name="InTargetPID">
  273
+            The target process ID.
  274
+            </param>
  275
+            <param name="InLibraryPath_x86">
  276
+            A partially qualified assembly name or a relative/absolute file path of the 32-bit version of your library. 
  277
+            For example "MyAssembly, PublicKeyToken=248973975895496" or ".\Assemblies\\MyAssembly.dll". 
  278
+            </param>
  279
+            <param name="InLibraryPath_x64">
  280
+            A partially qualified assembly name or a relative/absolute file path of the 64-bit version of your library. 
  281
+            For example "MyAssembly, PublicKeyToken=248973975895496" or ".\Assemblies\\MyAssembly.dll". 
  282
+            </param>
  283
+            <param name="InPassThruArgs">
  284
+            A serializable list of parameters being passed to your library entry points <c>Run()</c> and
  285
+            <c>Initialize()</c>.
  286
+            </param>
  287
+        </member>
  288
+        <member name="M:EasyHook.RemoteHooking.IsX64Process(System.Int32)">
  289
+            <summary>
  290
+            Determines if the target process is 64-bit or not. This will work only
  291
+            if the current process has <c>PROCESS_QUERY_INFORMATION</c> access to the target. 
  292
+            </summary>
  293
+            <remarks>
  294
+            A typical mistake is to enumerate processes under system privileges and 
  295
+            calling this method later when required. This won't work in most cases because
  296
+            you'll also need system privileges to run this method on processes in other sessions!
  297
+            </remarks>
  298
+            <param name="InTargetPID">The PID of the target process.</param>
  299
+            <returns><c>true</c> if the given process is 64-bit, <c>false</c> otherwise.</returns>
  300
+            <exception cref="T:System.AccessViolationException">
  301
+            The given process is not accessible.
  302
+            </exception>
  303
+            <exception cref="T:System.ArgumentException">
  304
+            The given process does not exist.
  305
+            </exception>
  306
+        </member>
  307
+        <member name="M:EasyHook.RemoteHooking.GetProcessIdentity(System.Int32)">
  308
+            <summary>
  309
+            Returns the <see cref="T:System.Security.Principal.WindowsIdentity"/> of the user the target process belongs to.
  310
+            You need <c>PROCESS_QUERY_INFORMATION</c> access to the target.
  311
+            </summary>
  312
+            <param name="InTargetPID">An accessible target process ID.</param>
  313
+            <returns>The identity of the target owner.</returns>
  314
+            <exception cref="T:System.AccessViolationException">
  315
+            The given process is not accessible.
  316
+            </exception>
  317
+            <exception cref="T:System.ArgumentException">
  318
+            The given process does not exist.
  319
+            </exception>
  320
+        </member>
  321
+        <member name="M:EasyHook.RemoteHooking.GetCurrentProcessId">
  322
+            <summary>
  323
+            Returns the current native system process ID.
  324
+            </summary>
  325
+            <returns>The native system process ID.</returns>
  326
+        </member>
  327
+        <member name="M:EasyHook.RemoteHooking.GetCurrentThreadId">
  328
+            <summary>
  329
+            Returns the current native system thread ID. 
  330
+            </summary>
  331
+            <remarks>
  332
+            Even if currently each dedicated managed
  333
+            thread (not a thread from a <see cref="T:System.Threading.ThreadPool"/>) exactly maps to one native
  334
+            system thread, this behavior may change in future versions. 
  335
+            If you would like to have unintercepted threads, you should make sure that they are
  336
+            dedicated ones, e.g. derived from <see cref="T:System.Threading.Thread"/>.
  337
+            </remarks>
  338
+            <returns>The native system thread ID.</returns>
  339
+        </member>
  340
+        <member name="M:EasyHook.RemoteHooking.ExecuteAsService``1(System.String,System.Object[])">
  341
+            <summary>
  342
+            Will execute the given static method under system privileges. 
  343
+            </summary>
  344
+            <remarks>
  345
+            <para>
  346
+            For some tasks it is necessary to have unrestricted access to the windows API.
  347
+            For example if you want to enumerate all running processes in all sessions. But
  348
+            keep in mind that you only can access these information within the given static
  349
+            method and only if it is called through this service.
  350
+            </para><para>
  351
+            To accomplish this task, your assembly is loaded into a system service which
  352
+            executes the given static method in a remoted manner. This implies that the
  353
+            return type shall be marked with <see cref="T:System.SerializableAttribute"/>. All
  354
+            handles or other process specific things obtained in the service, will be invalid 
  355
+            in your application after the call is completed! Also the service will use
  356
+            a new instance of your class, so you should only rely on the given parameters
  357
+            and avoid using any external variables.. Your method shall be threaded as isolated!
  358
+            </para><para>
  359
+            The next thing to mention is that all assemblies required for executing the method
  360
+            shall either be in the GAC or in the directory of the related EasyHook-Library.
  361
+            Otherwise the service won't be able to use your assembly!
  362
+            </para><para>
  363
+            All unhandled exceptions will be rethrown by the local <see cref="M:EasyHook.RemoteHooking.ExecuteAsService``1(System.String,System.Object[])"/>.
  364
+            </para>
  365
+            </remarks>
  366
+            <typeparam name="TClass">A class containing the given static method.</typeparam>
  367
+            <param name="InMethodName">A public static method exposed by the given public class.</param>
  368
+            <param name="InParams">A list of serializable parameters being passed to your static method.</param>
  369
+            <returns>The same value your method is returning or <c>null</c> if a <c>void</c> method is called.</returns>
  370
+            <exception cref="T:System.AccessViolationException">
  371
+            The current user is not an administrator.
  372
+            </exception>
  373
+            <example>
  374
+  <code>
  375
+private static void OnProcessUpdate(Object InCallback)
  376
+{
  377
+    ProcessTimer.Change(Timeout.Infinite, Timeout.Infinite);
  378
+
  379
+    try
  380
+    {
  381
+        ProcessInfo[] Array = (ProcessInfo[])RemoteHooking.ExecuteAsService&lt;Form1&gt;("EnumProcesses");
  382
+        SortedDictionary&lt;String, ProcessInfo&gt; Result = new SortedDictionary&lt;string, ProcessInfo&gt;();
  383
+
  384
+        // sort by name...
  385
+        lock (ProcessList)
  386
+        {
  387
+            ActivePIDList.Clear();
  388
+
  389
+            for (int i = 0; i &lt; Array.Length; i++)
  390
+            {
  391
+                Result.Add(System.IO.Path.GetFileName(Array[i].FileName) + "____" + i, Array[i]);
  392
+
  393
+                ActivePIDList.Add(Array[i].Id);
  394
+            }
  395
+
  396
+            Result.Values.CopyTo(Array, 0);
  397
+
  398
+            ProcessList.Clear();
  399
+
  400
+            ProcessList.AddRange(Array);
  401
+        }
  402
+    }
  403
+    catch (AccessViolationException)
  404
+    {
  405
+        MessageBox.Show("This is an administrative task!", "Permission denied...", MessageBoxButtons.OK);
  406
+
  407
+        Process.GetCurrentProcess().Kill();
  408
+    }
  409
+    finally
  410
+    {
  411
+        ProcessTimer.Change(5000, 5000);
  412
+    }
  413
+}
  414
+
  415
+[Serializable]
  416
+public class ProcessInfo
  417
+{
  418
+    public String FileName;
  419
+    public Int32 Id;
  420
+    public Boolean Is64Bit;
  421
+    public String User;
  422
+}
  423
+
  424
+public static ProcessInfo[] EnumProcesses()
  425
+{
  426
+    List&lt;ProcessInfo&gt; Result = new List&lt;ProcessInfo&gt;();
  427
+    Process[] ProcList = Process.GetProcesses();
  428
+
  429
+    for (int i = 0; i &lt; ProcList.Length; i++)
  430
+    {
  431
+        Process Proc = ProcList[i];
  432
+
  433
+        try
  434
+        {
  435
+            ProcessInfo Info = new ProcessInfo();
  436
+
  437
+            Info.FileName = Proc.MainModule.FileName;
  438
+            Info.Id = Proc.Id;
  439
+            Info.Is64Bit = RemoteHooking.IsX64Process(Proc.Id);
  440
+            Info.User = RemoteHooking.GetProcessIdentity(Proc.Id).Name;
  441
+
  442
+            Result.Add(Info);
  443
+        }
  444
+        catch
  445
+        {
  446
+        }
  447
+    }
  448
+
  449
+    return Result.ToArray();
  450
+}
  451
+  </code>
  452
+</example>
  453
+        </member>
  454
+        <member name="M:EasyHook.RemoteHooking.CreateAndInject(System.String,System.String,System.Int32,System.String,System.String,System.Int32@,System.Object[])">
  455
+            <summary>
  456
+            Creates a new process which is started suspended until you call <see cref="M:EasyHook.RemoteHooking.WakeUpProcess"/>
  457
+            from within your injected library <c>Run()</c> method. This allows you to hook the target
  458
+            BEFORE any of its usual code is executed. In situations where a target has debugging and
  459
+            hook preventions, you will get a chance to block those mechanisms for example...
  460
+            </summary>
  461
+            <remarks>
  462
+            <para>
  463
+            Please note that this method might fail when injecting into managed processes, especially
  464
+            when the target is using the CLR hosting API and takes advantage of AppDomains. For example,
  465
+            the Internet Explorer won't be hookable with this method. In such a case your only options
  466
+            are either to hook the target with the unmanaged API or to hook it after (non-supended) creation 
  467
+            with the usual <see cref="M:EasyHook.RemoteHooking.Inject(System.Int32,EasyHook.InjectionOptions,System.String,System.String,System.Object[])"/> method.
  468
+            </para>
  469
+            <para>
  470
+            See <see cref="M:EasyHook.RemoteHooking.Inject(System.Int32,EasyHook.InjectionOptions,System.String,System.String,System.Object[])"/> for more information. The exceptions listed here are additional
  471
+            to the ones listed for <see cref="M:EasyHook.RemoteHooking.Inject(System.Int32,EasyHook.InjectionOptions,System.String,System.String,System.Object[])"/>.
  472
+            </para>
  473
+            </remarks>
  474
+            <param name="InEXEPath">
  475
+            A relative or absolute path to the desired executable.
  476
+            </param>
  477
+            <param name="InCommandLine">
  478
+            Optional command line parameters for process creation.
  479
+            </param>
  480
+            <param name="InLibraryPath_x86">
  481
+            A partially qualified assembly name or a relative/absolute file path of the 32-bit version of your library. 
  482
+            For example "MyAssembly, PublicKeyToken=248973975895496" or ".\Assemblies\\MyAssembly.dll". 
  483
+            </param>
  484
+            <param name="InLibraryPath_x64">
  485
+            A partially qualified assembly name or a relative/absolute file path of the 64-bit version of your library. 
  486
+            For example "MyAssembly, PublicKeyToken=248973975895496" or ".\Assemblies\\MyAssembly.dll". 
  487
+            </param>
  488
+            <param name="OutProcessId">
  489
+            The process ID of the newly created process.
  490
+            </param>
  491
+            <param name="InPassThruArgs">
  492
+            A serializable list of parameters being passed to your library entry points <c>Run()</c> and
  493
+            <c>Initialize()</c>.
  494
+            </param>
  495
+            <exception cref="T:System.ArgumentException">
  496
+            The given EXE path could not be found.
  497
+            </exception>
  498
+        </member>
  499
+        <member name="M:EasyHook.RemoteHooking.InstallSupportDriver">
  500
+            <summary>
  501
+            Installs the EasyHook support driver. After this step you may use
  502
+            <see cref="M:EasyHook.RemoteHooking.InstallDriver(System.String,System.String)"/> to install your kernel mode hooking component.
  503
+            </summary>
  504
+        </member>
  505
+        <member name="M:EasyHook.RemoteHooking.InstallDriver(System.String,System.String)">
  506
+            <summary>
  507
+            Loads the given driver into the kernel and immediately marks it for deletion.
  508
+            The installed driver will be registered with the service control manager under the
  509
+            <paramref name="InDriverName"/> you specify.
  510
+            Please note that you should use <see cref="P:EasyHook.RemoteHooking.IsX64System"/> to find out which
  511
+            driver to load. Even if your process is running on 32-Bit this does not mean,
  512
+            that the OS kernel is running on 32-Bit!
  513
+            </summary>
  514
+            <param name="InDriverPath"></param>
  515
+            <param name="InDriverName"></param>
  516
+        </member>
  517
+        <member name="P:EasyHook.RemoteHooking.IsAdministrator">
  518
+            <summary>
  519
+            <c>true</c> if we are running with administrative privileges, <c>false</c> otherwise.
  520
+            </summary>
  521
+            <remarks>
  522
+            Due to UAC on Windows Vista, this property in general will be <c>false</c> even if the user is in
  523
+            the builtin-admin group. As you can't hook without administrator privileges you
  524
+            should just set the UAC level of your application to <c>requireAdministrator</c>.
  525
+            </remarks>
  526
+        </member>
  527
+        <member name="P:EasyHook.RemoteHooking.IsX64System">
  528
+            <summary>
  529
+            Returns <c>true</c> if the operating system is 64-Bit Windows, <c>false</c> otherwise.
  530
+            </summary>
  531
+        </member>
  532
+        <member name="T:EasyHook.RemoteHooking.IContext">
  533
+            <summary>
  534
+            A context contains some basic information about the environment
  535
+            in which your library main method has been invoked. You will always
  536
+            get an instance of this interface in your library <c>Run</c> method
  537
+            and your library <c>Initialize</c> method. 
  538
+            </summary>
  539
+        </member>
  540
+        <member name="P:EasyHook.RemoteHooking.IContext.HostPID">
  541
+            <summary>
  542
+            Returns the process ID of the host that has injected this library.
  543
+            </summary>
  544
+        </member>
  545
+        <member name="T:EasyHook.HookAccessControl">
  546
+            <summary>
  547
+            Provides a managed interface to the native thread ACLs.
  548
+            </summary>
  549
+            <remarks>
  550
+            Refer to the official guide to learn more about why thread ACLs are useful. 
  551
+            They can be used to exclude/include dedicated threads from interception or to dynamically
  552
+            apply different kind of hooks to different threads. Even if you could do this
  553
+            in managed code, it is not that easy to implement and also EasyHook evaluates
  554
+            those ACLs in unmanaged code. So if any thread is not intercepted, it will never
  555
+            enter the manged environment what will speed up things about orders of magnitudes.
  556
+            </remarks>
  557
+        </member>
  558
+        <member name="M:EasyHook.HookAccessControl.SetInclusiveACL(System.Int32[])">
  559
+            <summary>
  560
+            Sets an inclusive ACL. This means all threads that are enumerated through <paramref name="InACL"/>
  561
+            are intercepted while all others are NOT. Of course this will overwrite the existing ACL.
  562
+            </summary>
  563
+            <remarks>
  564
+            Please note that this is not necessarily the final
  565
+            negotiation result. Refer to <see cref="M:EasyHook.LocalHook.IsThreadIntercepted(System.Int32)"/> for more information.
  566
+            In general inclusive ACLs will restrict exclusive ACLs while local ACLs will overwrite the
  567
+            global ACL.
  568
+            </remarks>
  569
+            <param name="InACL">Threads to be explicitly included in negotiation.</param>
  570
+            <exception cref="T:System.ArgumentException">
  571
+            The limit of 128 access entries is exceeded!
  572
+            </exception>
  573
+        </member>
  574
+        <member name="M:EasyHook.HookAccessControl.SetExclusiveACL(System.Int32[])">
  575
+            <summary>
  576
+            Sets an exclusive ACL. This means all threads that are enumerated through <paramref name="InACL"/>
  577
+            are NOT intercepted while all others are. Of course this will overwrite the existing ACL.
  578
+            </summary>
  579
+            <remarks>
  580
+            Please note that this is not necessarily the final
  581
+            negotiation result. Refer to <see cref="M:EasyHook.LocalHook.IsThreadIntercepted(System.Int32)"/> for more information.
  582
+            In general inclusive ACLs will restrict exclusive ACLs while local ACLs will overwrite the
  583
+            global ACL.
  584
+            </remarks>
  585
+            <param name="InACL">Threads to be explicitly included in negotiation.</param>
  586
+            <exception cref="T:System.ArgumentException">
  587
+            The limit of 128 access entries is exceeded!
  588
+            </exception>
  589
+        </member>
  590
+        <member name="M:EasyHook.HookAccessControl.GetEntries">
  591
+            <summary>
  592
+            Creates a copy of the internal thread list associated with this ACL. You may freely
  593
+            modify it without affecting the internal entries.
  594
+            </summary>
  595
+            <returns>
  596
+            A copy of the internal thread entries.
  597
+            </returns>
  598
+        </member>
  599
+        <member name="P:EasyHook.HookAccessControl.IsExclusive">
  600
+            <summary>
  601
+            Is this ACL an exclusive one? Refer to <see cref="M:EasyHook.HookAccessControl.SetExclusiveACL(System.Int32[])"/> for more information.
  602
+            </summary>
  603
+        </member>
  604
+        <member name="P:EasyHook.HookAccessControl.IsInclusive">
  605
+            <summary>
  606
+            Is this ACL an inclusive one? Refer to <see cref="M:EasyHook.HookAccessControl.SetInclusiveACL(System.Int32[])"/> for more information.
  607
+            </summary>
  608
+        </member>
  609
+        <member name="T:EasyHook.HookRuntimeInfo">
  610
+            <summary>
  611
+            This class is intended to be used within hook handlers,
  612
+            to access associated runtime information.
  613
+            </summary>
  614
+            <remarks>
  615
+            Other hooking libraries on the market require that you keep track of
  616
+            such information yourself, what can be a burden.
  617
+            </remarks>
  618
+        </member>
  619
+        <member name="M:EasyHook.HookRuntimeInfo.UpdateUnmanagedModuleList">
  620
+            <summary>
  621
+            Allows you to explicitly update the unmanaged module list which is required for
  622
+            <see cref="P:EasyHook.HookRuntimeInfo.CallingUnmanagedModule"/>, <see cref="P:EasyHook.HookRuntimeInfo.UnmanagedStackTrace"/> and <see cref="M:EasyHook.HookRuntimeInfo.PointerToModule(System.IntPtr)"/>. 
  623
+            Normally this is not necessary, but if you hook a process that frequently loads/unloads modules, you
  624
+            may call this method in a <c>LoadLibrary</c> hook to always operate on the latest module list.
  625
+            </summary>
  626
+        </member>
  627
+        <member name="M:EasyHook.HookRuntimeInfo.PointerToModule(System.IntPtr)">
  628
+            <summary>
  629
+            Retrives the unmanaged module that contains the given pointer. If no module can be
  630
+            found, <c>null</c> is returned. This method will automatically update the unmanaged
  631
+            module list from time to time.
  632
+            Executes in less than one micro secound.
  633
+            </summary>
  634
+            <param name="InPointer"></param>
  635
+            <returns></returns>
  636
+        </member>
  637
+        <member name="P:EasyHook.HookRuntimeInfo.IsHandlerContext">
  638
+            <summary>
  639
+            Is the current thread within a valid hook handler? This is only the case
  640
+            if your handler was called through the hooked entry point...
  641
+            Executes in max. one micro secound.
  642
+            </summary>
  643
+        </member>
  644
+        <member name="P:EasyHook.HookRuntimeInfo.Callback">
  645
+            <summary>
  646
+            The user callback initially passed to either <see cref="M:EasyHook.LocalHook.Create(System.IntPtr,System.Delegate,System.Object)"/> or <see cref="M:EasyHook.LocalHook.CreateUnmanaged(System.IntPtr,System.IntPtr,System.IntPtr)"/>.
  647
+            Executes in max. one micro secound.
  648
+            </summary>
  649
+            <exception cref="T:System.NotSupportedException"> The current thread is not within a valid hook handler. </exception>
  650
+        </member>
  651
+        <member name="P:EasyHook.HookRuntimeInfo.Handle">
  652
+            <summary>
  653
+            The hook handle initially returned by either <see cref="M:EasyHook.LocalHook.Create(System.IntPtr,System.Delegate,System.Object)"/> or <see cref="M:EasyHook.LocalHook.CreateUnmanaged(System.IntPtr,System.IntPtr,System.IntPtr)"/>.
  654
+            Executes in max. one micro secound.
  655
+            </summary>
  656
+            <exception cref="T:System.NotSupportedException"> The current thread is not within a valid hook handler. </exception>
  657
+        </member>
  658
+        <member name="P:EasyHook.HookRuntimeInfo.CallingUnmanagedModule">
  659
+            <summary>
  660
+            Determines the first unmanaged module on the current call stack. This is always the module
  661
+            that invoked the hook. 
  662
+            Executes in max. 15 micro secounds.
  663
+            </summary>
  664
+            <remarks>
  665
+            The problem is that if the calling module is a NET assembly
  666
+            and invokes the hook through a P-Invoke binding, you will get
  667
+            "mscorwks.dll" as calling module and not the NET assembly. This is only an example 
  668
+            but I think you got the idea. To solve this issue, refer to <see cref="P:EasyHook.HookRuntimeInfo.UnmanagedStackTrace"/>
  669
+            and <see cref="P:EasyHook.HookRuntimeInfo.ManagedStackTrace"/>!
  670
+            </remarks>
  671
+        </member>
  672
+        <member name="P:EasyHook.HookRuntimeInfo.CallingManagedModule">
  673
+            <summary>
  674
+            Determines the first managed module on the current call stack. This is always the module
  675
+            that invoked the hook. 
  676
+            Executes in max. 40 micro secounds.
  677
+            </summary>
  678
+            <remarks>
  679
+            Imagine your hook targets CreateFile. A NET assembly will now invoke this hook through
  680
+            FileStream, for example. But because System.IO.FileStream invokes the hook, you will
  681
+            get "System.Core" as calling module and not the desired assembly.
  682
+            To solve this issue, refer to <see cref="P:EasyHook.HookRuntimeInfo.UnmanagedStackTrace"/>
  683
+            and <see cref="P:EasyHook.HookRuntimeInfo.ManagedStackTrace"/>!
  684
+            </remarks>
  685
+        </member>
  686
+        <member name="P:EasyHook.HookRuntimeInfo.ReturnAddress">
  687
+            <summary>
  688
+            Returns the address where execution is continued, after you hook has
  689
+            been completed. This is always the instruction behind the hook invokation.
  690
+            Executes in max. one micro secound.
  691
+            </summary>
  692
+        </member>
  693
+        <member name="P:EasyHook.HookRuntimeInfo.AddressOfReturnAddress">
  694
+            <summary>
  695
+            A stack address pointing to <see cref="P:EasyHook.HookRuntimeInfo.ReturnAddress"/>.
  696
+            Executes in max. one micro secound.
  697
+            </summary>
  698
+        </member>
  699
+        <member name="P:EasyHook.HookRuntimeInfo.UnmanagedStackTrace">
  700
+            <summary>
  701
+            Creates a call stack trace of the unmanaged code path that finally
  702
+            lead to your hook. To detect whether the desired module is within the
  703
+            call stack you will have to walk through the whole list!
  704
+            Executes in max. 20 micro secounds.
  705
+            </summary>
  706
+            <remarks>
  707
+            This method is not supported on Windows 2000 and will just return the
  708
+            calling unmanaged module wrapped in an array on that platform.
  709
+            </remarks>
  710
+        </member>
  711
+        <member name="P:EasyHook.HookRuntimeInfo.ManagedStackTrace">
  712
+            <summary>
  713
+            Creates a call stack trace of the managed code path that finally
  714
+            lead to your hook. To detect whether the desired module is within the
  715
+            call stack you will have to walk through the whole list!
  716
+            Executes in max. 80 micro secounds.
  717
+            </summary>
  718
+        </member>
  719
+        <member name="T:EasyHook.LocalHook">
  720
+            <summary>
  721
+            This class will provide various static members to be used with local hooking and
  722
+            is also the instance class of a hook.
  723
+            </summary>
  724
+            <remarks>
  725
+  The following demonstrates how to use <see cref="T:EasyHook.LocalHook"/>:
  726
+  <code>
  727
+using System;
  728
+using System.Collections.Generic;
  729
+using System.Text;
  730
+using System.Threading;
  731
+using System.Runtime.InteropServices;
  732
+using EasyHook;
  733
+
  734
+namespace FileMonInject
  735
+{
  736
+    public class Main : EasyHook.IEntryPoint
  737
+    {
  738
+        FileMon.FileMonInterface Interface;
  739
+        LocalHook CreateFileHook;
  740
+        Stack&lt;String&gt; Queue = new Stack&lt;String&gt; ();
  741
+
  742
+        public Main(
  743
+            RemoteHooking.IContext InContext,
  744
+            String InChannelName)
  745
+        {
  746
+            // connect to host...
  747
+            Interface = RemoteHooking.IpcConnectClient&lt;FileMon.FileMonInterface&gt;(InChannelName);
  748
+            
  749
+            // validate connection...
  750
+            Interface.Ping();
  751
+        }
  752
+
  753
+        public void Run(
  754
+            RemoteHooking.IContext InContext,
  755
+            String InChannelName)
  756
+        {
  757
+            // install hook...
  758
+            try
  759
+            {
  760
+                CreateFileHook = LocalHook.Create(
  761
+                    LocalHook.GetProcAddress("kernel32.dll", "CreateFileW"),
  762
+                    new DCreateFile(CreateFile_Hooked),
  763
+                    this);
  764
+                
  765
+                CreateFileHook.ThreadACL.SetExclusiveACL(new Int32[] { 0 });
  766
+            }
  767
+            catch (Exception ExtInfo)
  768
+            {
  769
+                Interface.ReportException(ExtInfo);
  770
+
  771
+                return;
  772
+            }
  773
+
  774
+            Interface.IsInstalled(RemoteHooking.GetCurrentProcessId());
  775
+
  776
+            RemoteHooking.WakeUpProcess();
  777
+
  778
+            // wait for host process termination...
  779
+            try
  780
+            {
  781
+                while (true)
  782
+                {
  783
+                    Thread.Sleep(500);
  784
+
  785
+                    // transmit newly monitored file accesses...
  786
+                    if (Queue.Count &gt; 0)
  787
+                    {
  788
+                        String[] Package = null;
  789
+
  790
+                        lock (Queue)
  791
+                        {
  792
+                            Package = Queue.ToArray();
  793
+
  794
+                            Queue.Clear();
  795
+                        }
  796
+
  797
+                        Interface.OnCreateFile(RemoteHooking.GetCurrentProcessId(), Package);
  798
+                    }
  799
+                    else
  800
+                        Interface.Ping();
  801
+                }
  802
+            }
  803
+            catch
  804
+            {
  805
+                // Ping() will raise an exception if host is unreachable
  806
+            }
  807
+        }
  808
+
  809
+        [UnmanagedFunctionPointer(CallingConvention.StdCall,
  810
+            CharSet = CharSet.Unicode,
  811
+            SetLastError = true)]
  812
+        delegate IntPtr DCreateFile(
  813
+            String InFileName,
  814
+            UInt32 InDesiredAccess,
  815
+            UInt32 InShareMode,
  816
+            IntPtr InSecurityAttributes,
  817
+            UInt32 InCreationDisposition,
  818
+            UInt32 InFlagsAndAttributes,
  819
+            IntPtr InTemplateFile);
  820
+
  821
+        // just use a P-Invoke implementation to get native API access from C# (this step is not necessary for C++.NET)
  822
+        [DllImport("kernel32.dll",
  823
+            CharSet = CharSet.Unicode,
  824
+            SetLastError = true,
  825
+            CallingConvention = CallingConvention.StdCall)]
  826
+        static extern IntPtr CreateFile(
  827
+            String InFileName,
  828
+            UInt32 InDesiredAccess,
  829
+            UInt32 InShareMode,
  830
+            IntPtr InSecurityAttributes,
  831
+            UInt32 InCreationDisposition,
  832
+            UInt32 InFlagsAndAttributes,
  833
+            IntPtr InTemplateFile);
  834
+
  835
+        // this is where we are intercepting all file accesses!
  836
+        static IntPtr CreateFile_Hooked(
  837
+            String InFileName,
  838
+            UInt32 InDesiredAccess,
  839
+            UInt32 InShareMode,
  840
+            IntPtr InSecurityAttributes,
  841
+            UInt32 InCreationDisposition,
  842
+            UInt32 InFlagsAndAttributes,
  843
+            IntPtr InTemplateFile)
  844
+        {
  845
+            
  846
+            try
  847
+            {
  848
+                Main This = (Main)HookRuntimeInfo.Callback;
  849
+
  850
+                lock (This.Queue)
  851
+                {
  852
+                    This.Queue.Push("[" + RemoteHooking.GetCurrentProcessId() + ":" + 
  853
+                        RemoteHooking.GetCurrentThreadId() +  "]: \"" + InFileName + "\"");
  854
+                }
  855
+            }
  856
+            catch
  857
+            {
  858
+            }
  859
+
  860
+            // call original API...
  861
+            return CreateFile(
  862
+                InFileName,
  863
+                InDesiredAccess,
  864
+                InShareMode,
  865
+                InSecurityAttributes,
  866
+                InCreationDisposition,
  867
+                InFlagsAndAttributes,
  868
+                InTemplateFile);
  869
+        }
  870
+    }
  871
+}
  872
+
  873
+  </code>
  874
+</remarks>
  875
+        </member>
  876
+        <member name="M:EasyHook.LocalHook.Finalize">
  877
+            <summary>
  878
+            Ensures that each instance is always terminated with <see cref="M:EasyHook.LocalHook.Dispose"/>.
  879
+            </summary>
  880
+        </member>
  881
+        <member name="M:EasyHook.LocalHook.IsThreadIntercepted(System.Int32)">
  882
+            <summary>
  883
+            Checks whether a given thread ID will be intercepted by the underlying hook.
  884
+            </summary>
  885
+            <remarks>
  886
+            <para>
  887
+            This method provides an interface to the internal negotiation algorithm.
  888
+            You may use it to check whether your ACL provides expected results.
  889
+            </para><para>
  890
+            The following is a pseudo code of how this method is implemented:
  891
+            <code>
  892
+            if(InThreadID == 0)
  893
+                InThreadID = GetCurrentThreadId();
  894
+            
  895
+            if(GlobalACL.Contains(InThreadID))
  896
+            {
  897
+                if(LocalACL.Contains(InThreadID))
  898
+            	{
  899
+            		if(LocalACL.IsExclusive)
  900
+            			return false;
  901
+            	}
  902
+            	else
  903
+            	{
  904
+            		if(GlobalACL.IsExclusive)
  905
+            			return false;
  906
+            
  907
+            		if(!LocalACL.IsExclusive)
  908
+            			return false;
  909
+            	}
  910
+            }
  911
+            else
  912
+            {
  913
+            	if(LocalACL.Contains(InThreadID))
  914
+            	{
  915
+            		if(LocalACL.IsExclusive)
  916
+            			return false;
  917
+            	}
  918
+            	else
  919
+            	{
  920
+            		if(!GlobalACL.IsExclusive)
  921
+            			return false;
  922
+            
  923
+            		if(!LocalACL.IsExclusive)
  924
+            			return false;
  925
+            	}
  926
+            }
  927
+            
  928
+            return true;
  929
+            </code>
  930
+            </para>
  931
+            </remarks>
  932
+            <param name="InThreadID">A native OS thread ID; or zero if you want to check the current thread.</param>
  933
+            <returns><c>true</c> if the thread is intercepted, <c>false</c> otherwise.</returns>
  934
+            <exception cref="T:System.ObjectDisposedException">
  935
+            The underlying hook is already disposed.
  936
+            </exception>
  937
+        </member>
  938
+        <member name="M:EasyHook.LocalHook.Dispose">
  939
+            <summary>
  940
+            If you want to immediately uninstall a hook, the only way is to dispose it. A disposed
  941
+            hook is guaranteed to never invoke your handler again but may still consume
  942
+            memory even for process life-time! 
  943
+            </summary>
  944
+            <remarks>
  945
+            As we are living in a manged world, you don't have to dispose a hook because the next 
  946
+            garbage collection will do it for you, assuming that your code does not reference it
  947
+            anymore. But there are times when you want to uninstall it excplicitly, with no delay.
  948
+            If you dispose a disposed or not installed hook, nothing will happen!
  949
+            </remarks>
  950
+        </member>
  951
+        <member name="M:EasyHook.LocalHook.Create(System.IntPtr,System.Delegate,System.Object)">
  952
+            <summary>
  953
+            Installs a managed hook. After this you'll have to activate it by setting a proper <see cref="P:EasyHook.LocalHook.ThreadACL"/>.
  954
+            </summary>
  955
+            <remarks>
  956
+            <para>
  957
+            Note that not all entry points are hookable! In general methods like <c>CreateFileW</c>
  958
+            won't cause any trouble. But there might be methods that are not hookable because their
  959
+            entry point machine code is not eligable to be hooked. You should test all hooks on
  960
+            common environments like "Windows XP x86/x64 SP2/SP3" and "Windows Vista x86/x64 (SP1)".
  961
+            This is the only way to ensure that your application will work well on most machines.
  962
+            </para><para>
  963
+            Your handler delegate has to use the <see cref="T:System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute"/> and
  964
+            shall map to the same native method signature, otherwise the application will crash! The best
  965
+            way is to use predefined delegates used in related P-Invoke implementations usually found with Google.
  966
+            If you know how to write such native delegates you won't need internet resources of course.
  967
+            I recommend using C++.NET which allows you to just copy the related windows API to your managed
  968
+            class and thread it as delegate without any changes. This will also speed up the whole thing
  969
+            because no unnecessary marshalling is required! C++.NET is also better in most cases because you
  970
+            may access the whole native windows API from managed code without any effort what significantly eases
  971
+            writing of hook handlers.
  972
+            </para>
  973
+            <para>
  974
+            The given delegate is automatically prevented from being garbage collected until the hook itself
  975
+            is collected...
  976
+            </para>
  977
+            </remarks>
  978
+            <param name="InTargetProc">A target entry point that should be hooked.</param>
  979
+            <param name="InNewProc">A handler with the same signature as the original entry point
  980
+            that will be invoked for every call that has passed the Fiber Deadlock Barrier and various integrity checks.</param>
  981
+            <param name="InCallback">An uninterpreted callback that will later be available through <see cref="P:EasyHook.HookRuntimeInfo.Callback"/>.</param>
  982
+            <returns>
  983
+            A handle to the newly created hook.
  984
+            </returns>
  985
+            <exception cref="T:System.OutOfMemoryException">
  986
+            Not enough memory available to complete the operation. On 64-Bit this may also indicate
  987
+            that no memory can be allocated within a 31-Bit boundary around the given entry point.
  988
+            </exception>
  989
+            <exception cref="T:System.ArgumentException">
  990
+            The given function pointer does not map to executable memory (valid machine code) or 
  991
+            you passed <c>null</c> as delegate.
  992
+            </exception>
  993
+            <exception cref="T:System.NotSupportedException">
  994
+            The given entry point contains machine code that can not be hooked.
  995
+            </exception>
  996
+            <exception cref="T:System.InsufficientMemoryException">
  997
+            The maximum amount of hooks has been installed. This is currently set to MAX_HOOK_COUNT (1024).
  998
+            </exception>
  999
+        </member>
  1000
+        <member name="M:EasyHook.LocalHook.CreateUnmanaged(System.IntPtr,System.IntPtr,System.IntPtr)">
  1001
+            <summary>
  1002
+            Installs an unmanaged hook. After this you'll have to activate it by setting a proper <see cref="P:EasyHook.LocalHook.ThreadACL"/>.
  1003
+            <see cref="T:EasyHook.HookRuntimeInfo"/> WON'T be supported! Refer to the native "LhBarrierXxx" APIs to
  1004
+            access unmanaged hook runtime information.
  1005
+            </summary>
  1006
+            <remarks>
  1007
+            <para>
  1008
+            Note that not all entry points are hookable! In general methods like <c>CreateFileW</c>
  1009
+            won't cause any trouble. But there may be methods that are not hookable because their
  1010
+            entry point machine code is not eligable to be hooked. You should test all hooks on
  1011
+            common environments like "Windows XP x86/x64 SP1/SP2/SP3" and "Windows Vista x86/x64 (SP1)".
  1012
+            This is the only way to ensure that your application will work well on most machines.
  1013
+            </para><para>
  1014
+            Unmanaged hooks will require a native DLL which handles the requests. This way
  1015
+            you will get a high-performance interface, because
  1016
+            a switch from unmanaged to managed code seems to be rather time consuming without doing anything
  1017
+            useful (at least nothing visible); so a hook omitting this switch will be handled one or two
  1018
+            orders of magnitudes faster until finally your handler gains execution. But as a managed hook is still executed
  1019
+            within at last 1000 nano-seconds, even the "slow" managed implementation will be fast enough in most
  1020
+            cases. With C++.NET you would be able to provide such native high-speed hooks for frequently
  1021
+            called API methods, while still using managed ones for usual API methods, within a single assembly!
  1022
+            A pure unmanaged, empty hook executes in approx. 70 nano-seconds, which is incredible fast
  1023
+            considering the thread deadlock barrier and thread ACL negotiation that are already included in this benchmark!
  1024
+            </para>
  1025
+            </remarks>
  1026
+            <param name="InTargetProc">A target entry point that should be hooked.</param>
  1027
+            <param name="InNewProc">A handler with the same signature as the original entry point
  1028
+            that will be invoked for every call that has passed the Thread Deadlock Barrier and various integrity checks.</param>
  1029
+            <param name="InCallback">An uninterpreted callback that will later be available through <c>LhBarrierGetCallback()</c>.</param>
  1030
+            <returns>
  1031
+            A handle to the newly created hook.
  1032
+            </returns>
  1033
+            <exception cref="T:System.OutOfMemoryException">
  1034
+            Not enough memory available to complete the operation. On 64-Bit this may also indicate
  1035
+            that no memory can be allocated within a 31-Bit boundary around the given entry point.
  1036
+            </exception>
  1037
+            <exception cref="T:System.ArgumentException">
  1038
+            The given function pointer does not map to executable memory (valid machine code) or 
  1039
+            you passed <c>null</c> as delegate.
  1040
+            </exception>
  1041
+            <exception cref="T:System.NotSupportedException">
  1042
+            The given entry point contains machine code that can not be hooked.
  1043
+            </exception>
  1044
+            <exception cref="T:System.InsufficientMemoryException">
  1045
+            The maximum amount of hooks has been installed. This is currently set to MAX_HOOK_COUNT (1024).
  1046
+            </exception>
  1047
+        </member>
  1048
+        <member name="M:EasyHook.LocalHook.GetProcAddress(System.String,System.String)">
  1049
+            <summary>
  1050
+            Will return the address for a given DLL export symbol. The specified
  1051
+            module has to be loaded into the current process space and also export
  1052
+            the given method.
  1053
+            </summary>
  1054
+            <remarks>
  1055
+            If you wonder how to get native entry points in a managed environment,
  1056
+            this is the anwser. You will only be able to hook native code from a managed
  1057
+            environment if you have access to a method like this, returning the native
  1058
+            entry point. Please note that you will also hook any managed code, which
  1059
+            of course ultimately relies on the native windows API!
  1060
+            </remarks>
  1061
+            <param name="InModule">A system DLL name like "kernel32.dll" or a full qualified path to any DLL.</param>
  1062
+            <param name="InSymbolName">An exported symbol name like "CreateFileW".</param>
  1063
+            <returns>The entry point for the given API method.</returns>
  1064
+            <exception cref="T:System.DllNotFoundException">
  1065
+            The given module is not loaded into the current process.
  1066
+            </exception>
  1067
+            <exception cref="T:System.MissingMethodException">
  1068
+            The given module does not export the desired method.
  1069
+            </exception>
  1070
+        </member>
  1071
+        <member name="M:EasyHook.LocalHook.GetProcDelegate``1(System.String,System.String)">
  1072
+            <summary>
  1073
+            Will return a delegate for a given DLL export symbol. The specified
  1074
+            module has to be loaded into the current process space and also export
  1075
+            the given method.
  1076
+            </summary>
  1077
+            <remarks><para>
  1078
+            This method is usually not useful to hook something but it allows you
  1079
+            to dynamically load native API methods into your managed environment instead
  1080
+            of using the static P-Invoke approach provided by <see cref="T:System.Runtime.InteropServices.DllImportAttribute"/>.
  1081
+            </para></remarks>
  1082
+            <typeparam name="TDelegate">A delegate using the <see cref="T:System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute"/> and
  1083
+            exposing the same method signature as the specified native symbol.</typeparam>
  1084
+            <param name="InModule">A system DLL name like "kernel32.dll" or a full qualified path to any DLL.</param>
  1085
+            <param name="InSymbolName">An exported symbol name like "CreateFileW".</param>
  1086
+            <returns>The managed delegate wrapping around the given native symbol.</returns>
  1087
+            <exception cref="T:System.DllNotFoundException">
  1088
+            The given module is not loaded into the current process.
  1089
+            </exception>
  1090
+            <exception cref="T:System.MissingMethodException">
  1091
+            The given module does not export the given method.
  1092
+            </exception>
  1093
+        </member>
  1094
+        <member name="M:EasyHook.LocalHook.EnableRIPRelocation">
  1095
+            <summary>
  1096
+            RIP relocation is disabled by default. If you want to enable it,
  1097
+            just call this method which will attach a debugger to the current
  1098
+            process. There may be circumstances under which this might fail
  1099
+            and this is why it is not done by default. On 32-Bit system this
  1100
+            method will always succeed and do nothing...
  1101
+            </summary>
  1102
+        </member>
  1103
+        <member name="M:EasyHook.LocalHook.GetThreadIdByHandle(System.IntPtr)">
  1104
+            <summary>
  1105
+            Tries to get the underlying thread ID for a given handle.
  1106
+            </summary>
  1107
+            <remarks>
  1108
+            This is not always possible. The handle has to be opened with <c>THREAD_QUERY_INFORMATION</c>
  1109
+            access. 
  1110
+            </remarks>
  1111
+            <param name="InThreadHandle">A valid thread handle.</param>
  1112
+            <returns>A valid thread ID associated with the given thread handle.</returns>
  1113
+            <exception cref="T:System.AccessViolationException">
  1114
+            The given handle was not opened with <c>THREAD_QUERY_INFORMATION</c> access.</exception>
  1115
+            <exception cref="T:System.ArgumentException">
  1116
+            The handle is invalid. 
  1117
+            </exception>
  1118
+            <exception cref="T:System.NotSupportedException">
  1119
+            Should never occur and just notifies you that a handle to thread ID conversion is not
  1120
+            available on the current platform.
  1121
+            </exception>
  1122
+        </member>
  1123
+        <member name="M:EasyHook.LocalHook.GetProcessIdByHandle(System.IntPtr)">
  1124
+            <summary>
  1125
+            Tries to get the underlying process ID for a given handle.
  1126
+            </summary>
  1127
+            <remarks>
  1128
+            This is not always possible. The handle has to be opened with <c>PROCESS_QUERY_INFORMATION</c>
  1129
+            access. 
  1130
+            </remarks>
  1131
+            <param name="InProcessHandle">A valid process handle.</param>
  1132
+            <returns>A valid process ID associated with the given process handle.</returns>
  1133
+            <exception cref="T:System.AccessViolationException">
  1134
+            The given handle was not opened with <c>PROCESS_QUERY_INFORMATION</c> access.</exception>
  1135
+            <exception cref="T:System.ArgumentException">
  1136
+            The handle is invalid. 
  1137
+            </exception>
  1138
+            <exception cref="T:System.NotSupportedException">
  1139
+            Should never occur and just notifies you that a handle to thread ID conversion is not
  1140
+            available on the current platform.
  1141
+            </exception>
  1142
+        </member>
  1143
+        <member name="M:EasyHook.LocalHook.GetNameByHandle(System.IntPtr)">
  1144
+            <summary>
  1145
+            Reads the kernel object name for a given windows usermode handle.
  1146
+            Executes in approx. 100 micro secounds.
  1147
+            </summary>
  1148
+            <remarks><para>
  1149
+            This allows you to translate a handle back to the associated filename for example.
  1150
+            But keep in mind that such names are only valid for kernel service routines, like
  1151
+            <c>NtCreateFile</c>. You won't have success when calling <c>CreateFile</c> on such
  1152
+            object names! The regular windows user mode API has some methods that will allow
  1153
+            you to convert such kernelmode names back into usermode names. I know this because I did it
  1154
+            some years ago but I've already forgotten how it has to be done! I can only give you
  1155
+            some hints: <c>FindFirstVolume()</c>, <c>FindFirstVolumeMountPoint()</c>,
  1156
+            <c>QueryDosDevice()</c>, <c>GetVolumePathNamesForVolumeName()</c>
  1157
+            </para>
  1158
+            <param name="InHandle">A valid usermode handle.</param>
  1159
+            </remarks>
  1160
+            <returns>The kernel object name associated with the given handle.</returns>
  1161
+            <exception cref="T:System.ArgumentException">
  1162
+            The given handle is invalid or could not be accessed for unknown reasons.
  1163
+            </exception>
  1164
+        </member>
  1165
+        <member name="P:EasyHook.LocalHook.Callback">
  1166
+            <summary>
  1167
+            The callback passed to <see cref="M:EasyHook.LocalHook.Create(System.IntPtr,System.Delegate,System.Object)"/>.
  1168
+            </summary>