using System; using System.Runtime.InteropServices; namespace Vanara.PInvoke { public static partial class Kernel32 { /// Adds a dynamic function table to the dynamic function table list. /// /// A pointer to an array of function entries. For a definition of the PRUNTIME_FUNCTION type, see rtlsupportapi.h. For more /// information on runtime function entries, see the calling convention documentation for the processor. /// /// The number of entries in the FunctionTable array. /// /// The base address to use when computing full virtual addresses from relative virtual addresses of function table entries. /// /// If the function succeeds, the return value is TRUE. Otherwise, the return value is FALSE. /// /// /// 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. /// /// /// 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. /// /// // 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); /// Retrieves a context record in the context of the caller. /// A pointer to a CONTEXT structure. /// This function does not return a value. // 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); /// Retrieves a context record in the context of the caller. /// /// The context flags to specify what aspects of the context to capture. See for pre-configured values. /// /// The captured CONTEXT structure. [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; } /// Removes a dynamic function table from the dynamic function table list. /// /// 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 PRUNTIME_FUNCTION type, see rtlsupportapi.h. /// /// If the function succeeds, the return value is TRUE. Otherwise, the return value is FALSE. /// /// 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. /// // 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); /// Removes a dynamic function table from the dynamic function table list. /// /// 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 PRUNTIME_FUNCTION type, see rtlsupportapi.h. /// /// If the function succeeds, the return value is TRUE. Otherwise, the return value is FALSE. /// /// 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. /// // 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); /// Adds a dynamic function table to the dynamic function table list. /// /// The identifier for the dynamic function table callback. The two low-order bits must be set. For example, BaseAddress|0x3. /// /// The base address of the region of memory managed by the callback function. /// The size of the region of memory managed by the callback function, in bytes. /// /// 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 PGET_RUNTIME_FUNCTION_CALLBACK type, see rtlsupportapi.h. /// /// A pointer to the user-defined data to be passed to the callback function. /// /// /// An optional pointer to a string that specifies the path of a DLL that provides function table entries that are outside the process. /// /// /// When a debugger unwinds to a function in the range of addresses managed by the callback function, it loads this DLL and calls the /// OUT_OF_PROCESS_FUNCTION_TABLE_CALLBACK_EXPORT_NAME function, whose type is POUT_OF_PROCESS_FUNCTION_TABLE_CALLBACK. /// For more information, see the definitions of these items in rtlsupportapi.h. /// /// /// If the function succeeds, the return value is TRUE. If the function fails, the return value is FALSE. /// /// /// 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. /// /// /// 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. /// /// /// For code that is generated from a template or generated only once during the life of the process, use the RtlAddFunctionTable function. /// /// // 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); /// Searches the active function tables for an entry that corresponds to the specified PC value. /// The virtual address of an instruction bundle within the function. /// The base address of module to which the function belongs. /// /// The global pointer value of the module. /// This parameter has a different declaration on x64 and ARM systems. For more information, see x64 Definition and ARM Definition. /// /// /// If there is no entry in the function table for the specified PC, the function returns NULL. Otherwise, the function /// returns the address of the function table entry that corresponds to the specified PC. /// // 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); /// Retrieves the base address of the image that contains the specified PC value. /// /// The PC value. The function searches all modules mapped into the address space of the calling process for a module that contains /// this value. /// /// /// 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. /// /// /// If the PC value is found, the function returns the base address of the image that contains the PC value. /// If no image contains the PC value, the function returns NULL. /// // 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); /// Restores the context of the caller to the specified context record. /// A pointer to a CONTEXT structure. /// /// A pointer to an EXCEPTION_RECORD structure. This parameter is optional and should typically be NULL. /// /// An exception record is used primarily with long jump and C++ catch-throw support. If the ExceptionCode member is /// STATUS_LONGJUMP, the ExceptionInformation member contains a pointer to a jump buffer. RtlRestoreContext will copy /// the non-volatile state from the jump buffer in to the context record before the context record is restored. /// /// /// If the ExceptionCode member is STATUS_UNWIND_CONSOLIDATE, the ExceptionInformation member contains a pointer to a /// callback function, such as a catch handler. RtlRestoreContext 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. /// /// /// This function does not return a value. // 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); /// Initiates an unwind of procedure call frames. /// /// A pointer to the call frame that is the target of the unwind. If this parameter is NULL, the function performs an exit unwind. /// /// The continuation address of the unwind. This parameter is ignored if TargetFrame is NULL. /// A pointer to an EXCEPTION_RECORD structure. /// A value to be placed in the integer function return register before continuing execution. /// This function does not return a value. // 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); /// Initiates an unwind of procedure call frames. /// /// A pointer to the call frame that is the target of the unwind. If this parameter is NULL, the function performs an exit unwind. /// /// The continuation address of the unwind. This parameter is ignored if TargetFrame is NULL. /// A pointer to an EXCEPTION_RECORD structure. /// A value to be placed in the integer function return register before continuing execution. /// This function does not return a value. // 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); /// Initiates an unwind of procedure call frames. /// /// A pointer to the call frame that is the target of the unwind. If this parameter is NULL, the function performs an exit unwind. /// /// The continuation address of the unwind. This parameter is ignored if TargetFrame is NULL. /// A pointer to an EXCEPTION_RECORD structure. /// A value to be placed in the integer function return register before continuing execution. /// A pointer to a CONTEXT structure that stores context during the unwind operation. /// /// A pointer to the unwind history table. This structure is processor specific. For definitions of this structure, see Winternl.h. /// /// This function does not return a value. /// The FRAME_POINTERS structure is defined as follows: // 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); /// Initiates an unwind of procedure call frames. /// /// A pointer to the call frame that is the target of the unwind. If this parameter is NULL, the function performs an exit unwind. /// /// The continuation address of the unwind. This parameter is ignored if TargetFrame is NULL. /// A pointer to an EXCEPTION_RECORD structure. /// A value to be placed in the integer function return register before continuing execution. /// A pointer to a CONTEXT structure that stores context during the unwind operation. /// /// A pointer to the unwind history table. This structure is processor specific. For definitions of this structure, see Winternl.h. /// /// This function does not return a value. /// The FRAME_POINTERS structure is defined as follows: // 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(); /// Retrieves the invocation context of the function that precedes the specified function context. /// /// The handler type. This parameter can be one of the following values. /// This parameter is only present on x64. /// /// /// /// Value /// Meaning /// /// /// UNW_FLAG_NHANDLER0x0 /// The function has no handler. /// /// /// UNW_FLAG_EHANDLER0x1 /// The function has an exception handler that should be called. /// /// /// UNW_FLAG_UHANDLER0x2 /// The function has a termination handler that should be called when unwinding an exception. /// /// /// UNW_FLAG_CHAININFO0x4 /// The FunctionEntry member is the contents of a previous function table entry. /// /// /// /// /// The base address of the module to which the function belongs. /// The virtual address where control left the specified function. /// /// The address of the function table entry for the specified function. To obtain the function table entry, call the /// RtlLookupFunctionEntry function. /// /// A pointer to a CONTEXT structure that represents the context of the previous frame. /// /// /// 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. /// /// This parameter is not present on x64. /// /// /// /// A pointer to a FRAME_POINTERS structure that receives the establisher frame pointer value. The real frame pointer is /// defined only if InFunction is 1. /// /// This parameter is of type PULONG64 on x64. /// /// An optional pointer to a context pointers structure. /// This function returns a pointer to an EXCEPTION_ROUTINE callback function. // 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); /// The handler type. [Flags] public enum UNW_FLAGS : uint { /// The function has no handler. UNW_FLAG_NHANDLER = 0x0, /// The function has an exception handler that should be called. UNW_FLAG_EHANDLER = 0x1, /// The function has a termination handler that should be called when unwinding an exception. UNW_FLAG_UHANDLER = 0x2, /// The FunctionEntry member is the contents of a previous function table entry. UNW_FLAG_CHAININFO = 0x4, /// Undocumented. UNW_FLAG_NO_EPILOGUE = 0x80000000, } public delegate EXCEPTION_DISPOSITION EXCEPTION_ROUTINE(ref EXCEPTION_RECORD ExceptionRecord, IntPtr EstablisherFrame, ref CONTEXT ContextRecord, IntPtr DispatcherContext); */ } }