Vanara/PInvoke/Kernel32/RtlSupportApi.cs

351 lines
24 KiB
C#

using System;
using System.Runtime.InteropServices;
namespace Vanara.PInvoke
{
public static partial class Kernel32
{
/// <summary>Adds a dynamic function table to the dynamic function table list.</summary>
/// <param name="FunctionTable">
/// A pointer to an array of function entries. For a definition of the <c>PRUNTIME_FUNCTION</c> type, see rtlsupportapi.h. For more
/// information on runtime function entries, see the calling convention documentation for the processor.
/// </param>
/// <param name="EntryCount">The number of entries in the FunctionTable array.</param>
/// <param name="BaseAddress">
/// The base address to use when computing full virtual addresses from relative virtual addresses of function table entries.
/// </param>
/// <returns>If the function succeeds, the return value is <c>TRUE</c>. Otherwise, the return value is <c>FALSE</c>.</returns>
/// <remarks>
/// <para>
/// Function tables are used on 64-bit Windows to determine how to unwind or walk the stack. These tables are usually generated by
/// the compiler and stored as part of the image. However, applications must provide the function table for dynamically generated
/// code. For more information about function tables, see the architecture guide for your system.
/// </para>
/// <para>
/// This function is useful for code that is generated from a template or generated only once during the life of the process. For
/// more dynamically generated code, use the RtlInstallFunctionTableCallback function.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/winnt/nf-winnt-rtladdfunctiontable NTSYSAPI BOOLEAN RtlAddFunctionTable(
// PRUNTIME_FUNCTION FunctionTable, DWORD EntryCount, DWORD64 BaseAddress );
[DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("rtlsupportapi.h", MSDNShortId = "4717f29e-c5f8-4b02-a7c8-edd065f1c793")]
[return: MarshalAs(UnmanagedType.U1)]
public static extern bool RtlAddFunctionTable([In] IMAGE_RUNTIME_FUNCTION_ENTRY[] FunctionTable, uint EntryCount, ulong BaseAddress);
/// <summary>Retrieves a context record in the context of the caller.</summary>
/// <param name="ContextRecord">A pointer to a CONTEXT structure.</param>
/// <returns>This function does not return a value.</returns>
// https://docs.microsoft.com/en-us/windows/win32/api/winnt/nf-winnt-rtlcapturecontext NTSYSAPI VOID RtlCaptureContext( PCONTEXT
// ContextRecord );
[DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("rtlsupportapi.h", MSDNShortId = "e2ce0cde-43ab-4681-be66-bd7509fd6ca2")]
public static extern void RtlCaptureContext(ref CONTEXT ContextRecord);
/// <summary>Retrieves a context record in the context of the caller.</summary>
/// <param name="contextFlags">
/// The context flags to specify what aspects of the context to capture. See <see cref="CONTEXT_FLAG"/> for pre-configured values.
/// </param>
/// <returns>The captured <c>CONTEXT</c> structure.</returns>
[PInvokeData("rtlsupportapi.h", MSDNShortId = "e2ce0cde-43ab-4681-be66-bd7509fd6ca2")]
public static CONTEXT RtlCaptureContext(uint contextFlags = uint.MaxValue)
{
if (contextFlags == uint.MaxValue) contextFlags = CONTEXT_FLAG.CONTEXT_ALL;
var ctx = new CONTEXT { ContextFlags = contextFlags };
RtlCaptureContext(ref ctx);
return ctx;
}
/// <summary>Removes a dynamic function table from the dynamic function table list.</summary>
/// <param name="FunctionTable">
/// A pointer to an array of function entries that were previously passed to RtlAddFunctionTable or an identifier previously passed
/// to RtlInstallFunctionTableCallback. For a definition of the <c>PRUNTIME_FUNCTION</c> type, see rtlsupportapi.h.
/// </param>
/// <returns>If the function succeeds, the return value is <c>TRUE</c>. Otherwise, the return value is <c>FALSE</c>.</returns>
/// <remarks>
/// Function tables are used on 64-bit Windows to determine how to unwind or walk the stack. These tables are usually generated by
/// the compiler and stored as part of the image. However, applications must provide the function table for dynamically generated
/// code. For more information about function tables, see the architecture guide for your system.
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/winnt/nf-winnt-rtldeletefunctiontable NTSYSAPI BOOLEAN RtlDeleteFunctionTable(
// PRUNTIME_FUNCTION FunctionTable );
[DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("rtlsupportapi.h", MSDNShortId = "42bc3d83-8053-40e9-b153-f68733d0cb2b")]
[return: MarshalAs(UnmanagedType.U1)]
public static extern bool RtlDeleteFunctionTable([In] IMAGE_RUNTIME_FUNCTION_ENTRY[] FunctionTable);
/// <summary>Removes a dynamic function table from the dynamic function table list.</summary>
/// <param name="FunctionTable">
/// A pointer to an array of function entries that were previously passed to RtlAddFunctionTable or an identifier previously passed
/// to RtlInstallFunctionTableCallback. For a definition of the <c>PRUNTIME_FUNCTION</c> type, see rtlsupportapi.h.
/// </param>
/// <returns>If the function succeeds, the return value is <c>TRUE</c>. Otherwise, the return value is <c>FALSE</c>.</returns>
/// <remarks>
/// Function tables are used on 64-bit Windows to determine how to unwind or walk the stack. These tables are usually generated by
/// the compiler and stored as part of the image. However, applications must provide the function table for dynamically generated
/// code. For more information about function tables, see the architecture guide for your system.
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/winnt/nf-winnt-rtldeletefunctiontable NTSYSAPI BOOLEAN RtlDeleteFunctionTable(
// PRUNTIME_FUNCTION FunctionTable );
[DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("rtlsupportapi.h", MSDNShortId = "42bc3d83-8053-40e9-b153-f68733d0cb2b")]
[return: MarshalAs(UnmanagedType.U1)]
public static extern bool RtlDeleteFunctionTable([In] ulong FunctionTable);
/// <summary>Adds a dynamic function table to the dynamic function table list.</summary>
/// <param name="TableIdentifier">
/// The identifier for the dynamic function table callback. The two low-order bits must be set. For example, BaseAddress|0x3.
/// </param>
/// <param name="BaseAddress">The base address of the region of memory managed by the callback function.</param>
/// <param name="Length">The size of the region of memory managed by the callback function, in bytes.</param>
/// <param name="Callback">
/// A pointer to the callback function that is called to retrieve the function table entries for the functions in the specified
/// region of memory. For a definition of the <c>PGET_RUNTIME_FUNCTION_CALLBACK</c> type, see rtlsupportapi.h.
/// </param>
/// <param name="Context">A pointer to the user-defined data to be passed to the callback function.</param>
/// <param name="OutOfProcessCallbackDll">
/// <para>
/// An optional pointer to a string that specifies the path of a DLL that provides function table entries that are outside the process.
/// </para>
/// <para>
/// When a debugger unwinds to a function in the range of addresses managed by the callback function, it loads this DLL and calls the
/// <c>OUT_OF_PROCESS_FUNCTION_TABLE_CALLBACK_EXPORT_NAME</c> function, whose type is <c>POUT_OF_PROCESS_FUNCTION_TABLE_CALLBACK</c>.
/// For more information, see the definitions of these items in rtlsupportapi.h.
/// </para>
/// </param>
/// <returns>If the function succeeds, the return value is <c>TRUE</c>. If the function fails, the return value is <c>FALSE</c>.</returns>
/// <remarks>
/// <para>
/// Function tables are used on 64-bit Windows to determine how to unwind or walk the stack. These tables are usually generated by
/// the compiler and stored as part of the image. However, applications must provide the function table for dynamically generated
/// code. For more information about function tables, see the architecture guide for your system.
/// </para>
/// <para>
/// This function is useful for very dynamic code. The application specifies the memory range for the generated code, but does not
/// need to generate a table until it is needed by an unwind request. At that time, the system calls the callback function with the
/// Context and the control address. The callback function must return the runtime function entry for the specified address. Be sure
/// to avoid creating a deadlock between the callback function and the code generator.
/// </para>
/// <para>
/// For code that is generated from a template or generated only once during the life of the process, use the RtlAddFunctionTable function.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/winnt/nf-winnt-rtlinstallfunctiontablecallback NTSYSAPI BOOLEAN
// RtlInstallFunctionTableCallback( DWORD64 TableIdentifier, DWORD64 BaseAddress, DWORD Length, PGET_RUNTIME_FUNCTION_CALLBACK
// Callback, PVOID Context, PCWSTR OutOfProcessCallbackDll );
[DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("rtlsupportapi.h", MSDNShortId = "63b35b17-0b0e-46ed-9dbf-98290ab08bd1")]
[return: MarshalAs(UnmanagedType.U1)]
public static extern bool RtlInstallFunctionTableCallback(ulong TableIdentifier, ulong BaseAddress, uint Length, GetRuntimeFunctionCallback Callback, IntPtr Context = default, [MarshalAs(UnmanagedType.LPWStr)] string OutOfProcessCallbackDll = null);
/// <summary>Searches the active function tables for an entry that corresponds to the specified PC value.</summary>
/// <param name="ControlPc">The virtual address of an instruction bundle within the function.</param>
/// <param name="ImageBase">The base address of module to which the function belongs.</param>
/// <param name="HistoryTable">
/// <para>The global pointer value of the module.</para>
/// <para>This parameter has a different declaration on x64 and ARM systems. For more information, see x64 Definition and ARM Definition.</para>
/// </param>
/// <returns>
/// If there is no entry in the function table for the specified PC, the function returns <c>NULL</c>. Otherwise, the function
/// returns the address of the function table entry that corresponds to the specified PC.
/// </returns>
// https://docs.microsoft.com/en-us/windows/win32/api/winnt/nf-winnt-rtllookupfunctionentry NTSYSAPI PRUNTIME_FUNCTION
// RtlLookupFunctionEntry( DWORD64 ControlPc, PDWORD64 ImageBase, PUNWIND_HISTORY_TABLE HistoryTable );
[DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("rtlsupportapi.h", MSDNShortId = "624b97fb-0453-4f47-b6bd-92aa14705e78")]
public static extern IntPtr RtlLookupFunctionEntry(ulong ControlPc, out ulong ImageBase, out UNWIND_HISTORY_TABLE HistoryTable);
/// <summary>Retrieves the base address of the image that contains the specified PC value.</summary>
/// <param name="PcValue">
/// The PC value. The function searches all modules mapped into the address space of the calling process for a module that contains
/// this value.
/// </param>
/// <param name="BaseOfImage">
/// The base address of the image containing the PC value. This value must be added to any relative addresses in the headers to
/// locate the image.
/// </param>
/// <returns>
/// <para>If the PC value is found, the function returns the base address of the image that contains the PC value.</para>
/// <para>If no image contains the PC value, the function returns <c>NULL</c>.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/win32/api/winnt/nf-winnt-rtlpctofileheader NTSYSAPI PVOID RtlPcToFileHeader( PVOID
// PcValue, PVOID *BaseOfImage );
[DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("rtlsupportapi.h", MSDNShortId = "690c9f20-d471-49c9-a40c-28926f03acac")]
public static extern IntPtr RtlPcToFileHeader(IntPtr PcValue, out IntPtr BaseOfImage);
/// <summary>Restores the context of the caller to the specified context record.</summary>
/// <param name="ContextRecord">A pointer to a CONTEXT structure.</param>
/// <param name="ExceptionRecord">
/// <para>A pointer to an EXCEPTION_RECORD structure. This parameter is optional and should typically be <c>NULL</c>.</para>
/// <para>
/// An exception record is used primarily with long jump and C++ catch-throw support. If the <c>ExceptionCode</c> member is
/// STATUS_LONGJUMP, the <c>ExceptionInformation</c> member contains a pointer to a jump buffer. <c>RtlRestoreContext</c> will copy
/// the non-volatile state from the jump buffer in to the context record before the context record is restored.
/// </para>
/// <para>
/// If the <c>ExceptionCode</c> member is STATUS_UNWIND_CONSOLIDATE, the <c>ExceptionInformation</c> member contains a pointer to a
/// callback function, such as a catch handler. <c>RtlRestoreContext</c> consolidates the call frames between its frame and the frame
/// specified in the context record before calling the callback function. This hides frames from any exception handling that might
/// occur in the callback function. The difference between this and a typical unwind is that the data on the stack is still present,
/// so frame data such as a throw object is still available. The callback function returns a new program counter to update in the
/// context record, which is then used in a normal restore context.
/// </para>
/// </param>
/// <returns>This function does not return a value.</returns>
// https://docs.microsoft.com/en-us/windows/win32/api/winnt/nf-winnt-rtlrestorecontext NTSYSAPI VOID RtlRestoreContext( PCONTEXT
// ContextRecord, _EXCEPTION_RECORD *ExceptionRecord );
[DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("rtlsupportapi.h", MSDNShortId = "f5304d17-bc67-4e0f-a535-efca4e65c74c")]
public static extern void RtlRestoreContext(ref CONTEXT ContextRecord, ref EXCEPTION_RECORD ExceptionRecord);
/// <summary>Initiates an unwind of procedure call frames.</summary>
/// <param name="TargetFrame">
/// A pointer to the call frame that is the target of the unwind. If this parameter is <c>NULL</c>, the function performs an exit unwind.
/// </param>
/// <param name="TargetIp">The continuation address of the unwind. This parameter is ignored if TargetFrame is <c>NULL</c>.</param>
/// <param name="ExceptionRecord">A pointer to an EXCEPTION_RECORD structure.</param>
/// <param name="ReturnValue">A value to be placed in the integer function return register before continuing execution.</param>
/// <returns>This function does not return a value.</returns>
// https://docs.microsoft.com/en-us/windows/win32/api/winnt/nf-winnt-rtlunwind NTSYSAPI VOID RtlUnwind( PVOID TargetFrame, PVOID
// TargetIp, PEXCEPTION_RECORD ExceptionRecord, PVOID ReturnValue );
[DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("rtlsupportapi.h", MSDNShortId = "254b2547-9d3d-468f-a360-20a12e9dd82e")]
public static extern void RtlUnwind([In, Optional] IntPtr TargetFrame, [In, Optional] IntPtr TargetIp, in EXCEPTION_RECORD ExceptionRecord, IntPtr ReturnValue);
/// <summary>Initiates an unwind of procedure call frames.</summary>
/// <param name="TargetFrame">
/// A pointer to the call frame that is the target of the unwind. If this parameter is <c>NULL</c>, the function performs an exit unwind.
/// </param>
/// <param name="TargetIp">The continuation address of the unwind. This parameter is ignored if TargetFrame is <c>NULL</c>.</param>
/// <param name="ExceptionRecord">A pointer to an EXCEPTION_RECORD structure.</param>
/// <param name="ReturnValue">A value to be placed in the integer function return register before continuing execution.</param>
/// <returns>This function does not return a value.</returns>
// https://docs.microsoft.com/en-us/windows/win32/api/winnt/nf-winnt-rtlunwind NTSYSAPI VOID RtlUnwind( PVOID TargetFrame, PVOID
// TargetIp, PEXCEPTION_RECORD ExceptionRecord, PVOID ReturnValue );
[DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("rtlsupportapi.h", MSDNShortId = "254b2547-9d3d-468f-a360-20a12e9dd82e")]
public static extern void RtlUnwind([In, Optional] IntPtr TargetFrame, [In, Optional] IntPtr TargetIp, [In, Optional] IntPtr ExceptionRecord, IntPtr ReturnValue);
/// <summary>Initiates an unwind of procedure call frames.</summary>
/// <param name="TargetFrame">
/// A pointer to the call frame that is the target of the unwind. If this parameter is <c>NULL</c>, the function performs an exit unwind.
/// </param>
/// <param name="TargetIp">The continuation address of the unwind. This parameter is ignored if TargetFrame is <c>NULL</c>.</param>
/// <param name="ExceptionRecord">A pointer to an EXCEPTION_RECORD structure.</param>
/// <param name="ReturnValue">A value to be placed in the integer function return register before continuing execution.</param>
/// <param name="ContextRecord">A pointer to a CONTEXT structure that stores context during the unwind operation.</param>
/// <param name="HistoryTable">
/// A pointer to the unwind history table. This structure is processor specific. For definitions of this structure, see Winternl.h.
/// </param>
/// <returns>This function does not return a value.</returns>
/// <remarks>The <c>FRAME_POINTERS</c> structure is defined as follows:</remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/winnt/nf-winnt-rtlunwindex NTSYSAPI VOID RtlUnwindEx( PVOID TargetFrame, PVOID
// TargetIp, PEXCEPTION_RECORD ExceptionRecord, PVOID ReturnValue, PCONTEXT ContextRecord, PUNWIND_HISTORY_TABLE HistoryTable );
[DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("rtlsupportapi.h", MSDNShortId = "3d2d8778-311e-4cc1-b280-4f83ab457755")]
public static extern void RtlUnwindEx([In, Optional] IntPtr TargetFrame, [In, Optional] IntPtr TargetIp, in EXCEPTION_RECORD ExceptionRecord, IntPtr ReturnValue, in CONTEXT ContextRecord, in UNWIND_HISTORY_TABLE HistoryTable);
/// <summary>Initiates an unwind of procedure call frames.</summary>
/// <param name="TargetFrame">
/// A pointer to the call frame that is the target of the unwind. If this parameter is <c>NULL</c>, the function performs an exit unwind.
/// </param>
/// <param name="TargetIp">The continuation address of the unwind. This parameter is ignored if TargetFrame is <c>NULL</c>.</param>
/// <param name="ExceptionRecord">A pointer to an EXCEPTION_RECORD structure.</param>
/// <param name="ReturnValue">A value to be placed in the integer function return register before continuing execution.</param>
/// <param name="ContextRecord">A pointer to a CONTEXT structure that stores context during the unwind operation.</param>
/// <param name="HistoryTable">
/// A pointer to the unwind history table. This structure is processor specific. For definitions of this structure, see Winternl.h.
/// </param>
/// <returns>This function does not return a value.</returns>
/// <remarks>The <c>FRAME_POINTERS</c> structure is defined as follows:</remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/winnt/nf-winnt-rtlunwindex NTSYSAPI VOID RtlUnwindEx( PVOID TargetFrame, PVOID
// TargetIp, PEXCEPTION_RECORD ExceptionRecord, PVOID ReturnValue, PCONTEXT ContextRecord, PUNWIND_HISTORY_TABLE HistoryTable );
[DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("rtlsupportapi.h", MSDNShortId = "3d2d8778-311e-4cc1-b280-4f83ab457755")]
public static extern void RtlUnwindEx([In, Optional] IntPtr TargetFrame, [In, Optional] IntPtr TargetIp, [In, Optional] IntPtr ExceptionRecord, IntPtr ReturnValue, in CONTEXT ContextRecord, [In, Optional] IntPtr HistoryTable);
/*
public static extern void RtlCaptureStackBackTrace();
public static extern void RtlCompareMemory();
public static extern void RtlCopyMemory();
public static extern void RtlFillMemory();
/// <summary>Retrieves the invocation context of the function that precedes the specified function context.</summary>
/// <param name="HandlerType">
/// <para>The handler type. This parameter can be one of the following values.</para>
/// <para>This parameter is only present on x64.</para>
/// <para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>UNW_FLAG_NHANDLER0x0</term>
/// <term>The function has no handler.</term>
/// </item>
/// <item>
/// <term>UNW_FLAG_EHANDLER0x1</term>
/// <term>The function has an exception handler that should be called.</term>
/// </item>
/// <item>
/// <term>UNW_FLAG_UHANDLER0x2</term>
/// <term>The function has a termination handler that should be called when unwinding an exception.</term>
/// </item>
/// <item>
/// <term>UNW_FLAG_CHAININFO0x4</term>
/// <term>The FunctionEntry member is the contents of a previous function table entry.</term>
/// </item>
/// </list>
/// </para>
/// </param>
/// <param name="ImageBase">The base address of the module to which the function belongs.</param>
/// <param name="ControlPC">The virtual address where control left the specified function.</param>
/// <param name="FunctionEntry">
/// The address of the function table entry for the specified function. To obtain the function table entry, call the
/// <c>RtlLookupFunctionEntry</c> function.
/// </param>
/// <param name="ContextRecord">A pointer to a <c>CONTEXT</c> structure that represents the context of the previous frame.</param>
/// <param name="InFunction">
/// <para>
/// The location of the PC. If this parameter is 0, the PC is in the prologue, epilogue, or a null frame region of the function. If
/// this parameter is 1, the PC is in the body of the function.
/// </para>
/// <para>This parameter is not present on x64.</para>
/// </param>
/// <param name="EstablisherFrame">
/// <para>
/// A pointer to a <c>FRAME_POINTERS</c> structure that receives the establisher frame pointer value. The real frame pointer is
/// defined only if InFunction is 1.
/// </para>
/// <para>This parameter is of type <c>PULONG64</c> on x64.</para>
/// </param>
/// <param name="ContextPointers">An optional pointer to a context pointers structure.</param>
/// <returns>This function returns a pointer to an EXCEPTION_ROUTINE callback function.</returns>
// PEXCEPTION_ROUTINE WINAPI RtlVirtualUnwind( _In_ HandlerType, _In_ ImageBase, _In_ ControlPC, _In_ FunctionEntry, _Inout_
// ContextRecord, _Out_ InFunction, _Out_ EstablisherFrame, _Inout_opt_ ContextPointers); https://msdn.microsoft.com/en-us/library/windows/desktop/ms680617(v=vs.85).aspx
[DllImport(Lib.Kernel32, SetLastError = false, EntryPoint = "RtlVirtualUnwind")]
[PInvokeData("rtlsupportapi.h", MSDNShortId = "ms680617")]
public static extern EXCEPTION_ROUTINE RtlVirtualUnwindX64(UNW_FLAGS HandlerType, UIntPtr ImageBase, UIntPtr ControlPC, IntPtr FunctionEntry, ref CONTEXT ContextRecord, out IntPtr HandlerData, out ulong EstablisherFrame, IntPtr ContextPointers);
/// <summary>The handler type.</summary>
[Flags]
public enum UNW_FLAGS : uint
{
/// <summary>The function has no handler.</summary>
UNW_FLAG_NHANDLER = 0x0,
/// <summary>The function has an exception handler that should be called.</summary>
UNW_FLAG_EHANDLER = 0x1,
/// <summary>The function has a termination handler that should be called when unwinding an exception.</summary>
UNW_FLAG_UHANDLER = 0x2,
/// <summary>The FunctionEntry member is the contents of a previous function table entry.</summary>
UNW_FLAG_CHAININFO = 0x4,
/// <summary>Undocumented.</summary>
UNW_FLAG_NO_EPILOGUE = 0x80000000,
}
public delegate EXCEPTION_DISPOSITION EXCEPTION_ROUTINE(ref EXCEPTION_RECORD ExceptionRecord, IntPtr EstablisherFrame, ref CONTEXT ContextRecord, IntPtr DispatcherContext);
*/
}
}