Vanara/PInvoke/Kernel32/ErrHandlingApi.cs

1276 lines
69 KiB
C#
Raw Normal View History

2018-05-13 23:41:49 -04:00
using System;
using System.Linq;
2018-05-13 23:41:49 -04:00
using System.Runtime.InteropServices;
using System.Text;
2018-05-13 23:41:49 -04:00
using Vanara.Extensions;
using Vanara.InteropServices;
namespace Vanara.PInvoke
{
public static partial class Kernel32
{
/// <summary>The exception maximum parameters</summary>
public const int EXCEPTION_MAXIMUM_PARAMETERS = 15;
/// <summary>
2018-10-26 14:24:07 -04:00
/// An application-defined function that passes unhandled exceptions to the debugger, if the process is being debugged. Otherwise, it
/// optionally displays an Application Error message box and causes the exception handler to be executed. This function can be called
/// only from within the filter expression of an exception handler.
2018-05-13 23:41:49 -04:00
/// </summary>
/// <param name="ExceptionInfo">
2018-10-26 14:24:07 -04:00
/// A pointer to an EXCEPTION_POINTERS structure that specifies a description of the exception and the processor context at the time
/// of the exception. This pointer is the return value of a call to the GetExceptionInformation function.
2018-05-13 23:41:49 -04:00
/// </param>
/// <returns>
/// The function returns one of the following values.
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>EXCEPTION_CONTINUE_SEARCH = 0x0</term>
/// <term>The process is being debugged, so the exception should be passed (as second chance) to the application's debugger.</term>
/// </item>
/// <item>
/// <term>EXCEPTION_EXECUTE_HANDLER = 0x1</term>
/// <term>
2018-10-26 14:24:07 -04:00
/// If the SEM_NOGPFAULTERRORBOX flag was specified in a previous call to SetErrorMode, no Application Error message box is
/// displayed. The function returns control to the exception handler, which is free to take any appropriate action.
2018-05-13 23:41:49 -04:00
/// </term>
/// </item>
/// </list>
/// </returns>
2018-10-26 14:24:07 -04:00
public delegate EXCEPTION_FLAG PTOP_LEVEL_EXCEPTION_FILTER(in EXCEPTION_POINTERS ExceptionInfo);
2018-05-13 23:41:49 -04:00
/// <summary>
2018-10-26 14:24:07 -04:00
/// An application-defined function that serves as a vectored exception handler. Specify this address when calling the
/// AddVectoredExceptionHandler function.
2018-05-13 23:41:49 -04:00
/// </summary>
/// <param name="ExceptionInfo">A pointer to an EXCEPTION_POINTERS structure that receives the exception record.</param>
/// <returns>
2018-10-26 14:24:07 -04:00
/// To return control to the point at which the exception occurred, return EXCEPTION_CONTINUE_EXECUTION (0xffffffff). To continue the
/// handler search, return EXCEPTION_CONTINUE_SEARCH (0x0).
2018-05-13 23:41:49 -04:00
/// </returns>
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate int PVECTORED_EXCEPTION_HANDLER(ref EXCEPTION_POINTERS ExceptionInfo);
/// <summary>Exception flags</summary>
public enum EXCEPTION_FLAG : uint
{
/// <summary>Indicates a continuable exception.</summary>
EXCEPTION_CONTINUABLE = 0,
/// <summary>
2018-10-26 14:24:07 -04:00
/// Proceed with normal execution of UnhandledExceptionFilter. That means obeying the SetErrorMode flags, or invoking the
/// Application Error pop-up message box.
2018-05-13 23:41:49 -04:00
/// </summary>
EXCEPTION_CONTINUE_SEARCH = 0x0000,
/// <summary>Indicates a noncontinuable exception.</summary>
EXCEPTION_NONCONTINUABLE = 0x0001,
2018-10-26 14:24:07 -04:00
/// <summary>
/// Return from UnhandledExceptionFilter and execute the associated exception handler. This usually results in process termination.
/// </summary>
2018-05-13 23:41:49 -04:00
EXCEPTION_EXECUTE_HANDLER = 0x0001,
EXCEPTION_UNWINDING = 0x0002,
EXCEPTION_EXIT_UNWIND = 0x0004,
EXCEPTION_STACK_INVALID = 0x0008,
EXCEPTION_NESTED_CALL = 0x0010,
EXCEPTION_TARGET_UNWIND = 0x0020,
EXCEPTION_COLLIDED_UNWIND = 0x0040,
EXCEPTION_UNWIND = 0x0066,
/// <summary>
2018-10-26 14:24:07 -04:00
/// Return from UnhandledExceptionFilter and continue execution from the point of the exception. Note that the filter function is
/// free to modify the continuation state by modifying the exception information supplied through its LPEXCEPTION_POINTERS parameter.
2018-05-13 23:41:49 -04:00
/// </summary>
EXCEPTION_CONTINUE_EXECUTION = 0xFFFFFFFF,
EXCEPTION_CHAIN_END = 0xFFFFFFFF,
}
/// <summary>Flags that control the behavior of <see cref="RaiseFailFastException"/>.</summary>
public enum FAIL_FAST_FLAGS : uint
{
/// <summary>None.</summary>
NONE = 0,
/// <summary>
2018-10-26 14:24:07 -04:00
/// Causes RaiseFailFastException to set the ExceptionAddress of EXCEPTION_RECORD to the return address of this function (the
/// next instruction in the caller after the call to RaiseFailFastException). This function will set the exception address only
/// if ExceptionAddress is not NULL.
2018-05-13 23:41:49 -04:00
/// </summary>
FAIL_FAST_GENERATE_EXCEPTION_ADDRESS = 0x1,
}
/// <summary>
2018-11-28 14:33:55 -05:00
/// Flags passed to the <see cref="FormatMessage(uint, string[], HINSTANCE, FormatMessageFlags, uint)"/> method.
2018-05-13 23:41:49 -04:00
/// </summary>
[PInvokeData("winbase.h")]
[Flags]
public enum FormatMessageFlags
{
/// <summary>
2018-10-26 14:24:07 -04:00
/// The function allocates a buffer large enough to hold the formatted message, and places a pointer to the allocated buffer at
/// the address specified by lpBuffer. The nSize parameter specifies the minimum number of TCHARs to allocate for an output
/// message buffer. The caller should use the LocalFree function to free the buffer when it is no longer needed.
2018-05-13 23:41:49 -04:00
/// <para>
2018-10-26 14:24:07 -04:00
/// If the length of the formatted message exceeds 128K bytes, then FormatMessage will fail and a subsequent call to GetLastError
/// will return ERROR_MORE_DATA.
2018-05-13 23:41:49 -04:00
/// </para>
/// <para>
2018-10-26 14:24:07 -04:00
/// In previous versions of Windows, this value was not available for use when compiling Windows Store apps. As of Windows 10
/// this value can be used.
2018-05-13 23:41:49 -04:00
/// </para>
/// <para>
2018-10-26 14:24:07 -04:00
/// Windows Server 2003 and Windows XP: If the length of the formatted message exceeds 128K bytes, then FormatMessage will not
/// automatically fail with an error of ERROR_MORE_DATA.
2018-05-13 23:41:49 -04:00
/// </para>
/// <para>
2018-10-26 14:24:07 -04:00
/// Windows 10: LocalFree is not in the modern SDK, so it cannot be used to free the result buffer. Instead, use HeapFree
/// (GetProcessHeap(), allocatedMessage). In this case, this is the same as calling LocalFree on memory.
2018-05-13 23:41:49 -04:00
/// </para>
/// <para>
2018-10-26 14:24:07 -04:00
/// Important: LocalAlloc() has different options: LMEM_FIXED, and LMEM_MOVABLE. FormatMessage() uses LMEM_FIXED, so HeapFree can
/// be used. If LMEM_MOVABLE is used, HeapFree cannot be used.
2018-05-13 23:41:49 -04:00
/// </para>
/// </summary>
FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x100,
/// <summary>
2018-10-26 14:24:07 -04:00
/// The Arguments parameter is not a va_list structure, but is a pointer to an array of values that represent the arguments. This
/// flag cannot be used with 64-bit integer values. If you are using a 64-bit integer, you must use the va_list structure.
2018-05-13 23:41:49 -04:00
/// </summary>
FORMAT_MESSAGE_ARGUMENT_ARRAY = 0x2000,
/// <summary>
2018-10-26 14:24:07 -04:00
/// The lpSource parameter is a module handle containing the message-table resource(s) to search. If this lpSource handle is
/// NULL, the current process's application image file will be searched. This flag cannot be used with <see cref="FORMAT_MESSAGE_FROM_STRING"/>.
2018-05-13 23:41:49 -04:00
/// <para>If the module has no message table resource, the function fails with ERROR_RESOURCE_TYPE_NOT_FOUND.</para>
/// </summary>
FORMAT_MESSAGE_FROM_HMODULE = 0x800,
/// <summary>
2018-10-26 14:24:07 -04:00
/// The lpSource parameter is a pointer to a null-terminated string that contains a message definition. The message definition
/// may contain insert sequences, just as the message text in a message table resource may. This flag cannot be used with <see
/// cref="FORMAT_MESSAGE_FROM_HMODULE"/> or <see cref="FORMAT_MESSAGE_FROM_SYSTEM"/>.
2018-05-13 23:41:49 -04:00
/// </summary>
FORMAT_MESSAGE_FROM_STRING = 0x400,
/// <summary>
/// The function should search the system message-table resource(s) for the requested message. If this flag is specified with
2018-10-26 14:24:07 -04:00
/// <see cref="FORMAT_MESSAGE_FROM_HMODULE"/>, the function searches the system message table if the message is not found in the
/// module specified by lpSource. This flag cannot be used with <see cref="FORMAT_MESSAGE_FROM_STRING"/>.
2018-05-13 23:41:49 -04:00
/// <para>
2018-10-26 14:24:07 -04:00
/// If this flag is specified, an application can pass the result of the GetLastError function to retrieve the message text for a
/// system-defined error.
2018-05-13 23:41:49 -04:00
/// </para>
/// </summary>
FORMAT_MESSAGE_FROM_SYSTEM = 0x1000,
/// <summary>
2018-10-26 14:24:07 -04:00
/// Insert sequences in the message definition are to be ignored and passed through to the output buffer unchanged. This flag is
/// useful for fetching a message for later formatting. If this flag is set, the Arguments parameter is ignored.
2018-05-13 23:41:49 -04:00
/// </summary>
FORMAT_MESSAGE_IGNORE_INSERTS = 0x200,
/// <summary>
2018-10-26 14:24:07 -04:00
/// The function ignores regular line breaks in the message definition text. The function stores hard-coded line breaks in the
/// message definition text into the output buffer. The function generates no new line breaks.
2018-05-13 23:41:49 -04:00
/// <para>
2018-10-26 14:24:07 -04:00
/// Without this flag set: There are no output line width restrictions. The function stores line breaks that are in the message
/// definition text into the output buffer. It specifies the maximum number of characters in an output line. The function ignores
/// regular line breaks in the message definition text. The function never splits a string delimited by white space across a line
/// break. The function stores hard-coded line breaks in the message definition text into the output buffer. Hard-coded line
/// breaks are coded with the %n escape sequence.
2018-05-13 23:41:49 -04:00
/// </para>
/// </summary>
FORMAT_MESSAGE_MAX_WIDTH_MASK = 0xff
}
/// <summary>Registers a vectored continue handler.</summary>
/// <param name="FirstHandler">
2018-10-26 14:24:07 -04:00
/// The order in which the handler should be called. If the parameter is nonzero, the handler is the first handler to be called. If
/// the parameter is zero, the handler is the last handler to be called.
2018-05-13 23:41:49 -04:00
/// </param>
/// <param name="VectoredHandler">A pointer to the handler to be called. For more information, see VectoredHandler.</param>
/// <returns>
/// <para>If the function succeeds, the return value is a handle to the exception handler.</para>
/// <para>If the function fails, the return value is <c>NULL</c>.</para>
/// </returns>
// PVOID WINAPI AddVectoredContinueHandler( _In_ ULONG FirstHandler, _In_ PVECTORED_EXCEPTION_HANDLER VectoredHandler);
[DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("WinBase.h", MSDNShortId = "ms679273")]
public static extern SafeContinueHandlerHandle AddVectoredContinueHandler(uint FirstHandler, PVECTORED_EXCEPTION_HANDLER VectoredHandler);
/// <summary>Registers a vectored exception handler.</summary>
/// <param name="FirstHandler">
2018-10-26 14:24:07 -04:00
/// The order in which the handler should be called. If the parameter is nonzero, the handler is the first handler to be called. If
/// the parameter is zero, the handler is the last handler to be called.
2018-05-13 23:41:49 -04:00
/// </param>
/// <param name="VectoredHandler">A pointer to the handler to be called. For more information, see <c>VectoredHandler</c>.</param>
/// <returns>
/// <para>If the function succeeds, the return value is a handle to the exception handler.</para>
/// <para>If the function fails, the return value is <c>NULL</c>.</para>
/// </returns>
// PVOID WINAPI AddVectoredExceptionHandler( _In_ ULONG FirstHandler, _In_ PVECTORED_EXCEPTION_HANDLER VectoredHandler);
[DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("WinBase.h", MSDNShortId = "ms679274")]
public static extern SafeExceptionHandlerHandle AddVectoredExceptionHandler(uint FirstHandler, PVECTORED_EXCEPTION_HANDLER VectoredHandler);
/// <summary>
2018-10-26 14:24:07 -04:00
/// Displays a message box and terminates the application when the message box is closed. If the system is running with a debug
/// version of Kernel32.dll, the message box gives the user the opportunity to terminate the application or to cancel the message box
/// and return to the application that called <c>FatalAppExit</c>.
2018-05-13 23:41:49 -04:00
/// </summary>
/// <param name="uAction">This parameter must be zero.</param>
/// <param name="lpMessageText">The null-terminated string that is displayed in the message box.</param>
/// <returns>This function does not return a value.</returns>
// void WINAPI FatalAppExit( _In_ UINT uAction, _In_ LPCTSTR lpMessageText); https://msdn.microsoft.com/en-us/library/windows/desktop/ms679336(v=vs.85).aspx
[DllImport(Lib.Kernel32, SetLastError = false, CharSet = CharSet.Auto)]
[PInvokeData("WinBase.h", MSDNShortId = "ms679336")]
2018-10-26 14:24:07 -04:00
public static extern void FatalAppExit(uint uAction, string lpMessageText);
2018-05-13 23:41:49 -04:00
/// <summary>
2018-10-26 14:24:07 -04:00
/// Formats a message string. The function requires a message definition as input. The message definition can come from a buffer
/// passed into the function. It can come from a message table resource in an already-loaded module. Or the caller can ask the
/// function to search the system's message table resource(s) for the message definition. The function finds the message definition
/// in a message table resource based on a message identifier and a language identifier. The function copies the formatted message
/// text to an output buffer, processing any embedded insert sequences if requested.
2018-05-13 23:41:49 -04:00
/// </summary>
/// <param name="dwFlags">
/// <para>
2018-10-26 14:24:07 -04:00
/// The formatting options, and how to interpret the lpSource parameter. The low-order byte of dwFlags specifies how the function
/// handles line breaks in the output buffer. The low-order byte can also specify the maximum width of a formatted output line.
2018-05-13 23:41:49 -04:00
/// </para>
/// <para>This parameter can be one or more of the following values.</para>
/// <para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>FORMAT_MESSAGE_ALLOCATE_BUFFER0x00000100</term>
/// <term>
2018-10-26 14:24:07 -04:00
/// The function allocates a buffer large enough to hold the formatted message, and places a pointer to the allocated buffer at the
/// address specified by lpBuffer. The lpBuffer parameter is a pointer to an LPTSTR; you must cast the pointer to an LPTSTR (for
/// example, ). The nSize parameter specifies the minimum number of TCHARs to allocate for an output message buffer. The caller
/// should use the LocalFree function to free the buffer when it is no longer needed.If the length of the formatted message exceeds
/// 128K bytes, then FormatMessage will fail and a subsequent call to GetLastError will return ERROR_MORE_DATA.In previous versions
/// of Windows, this value was not available for use when compiling Windows Store apps. As of Windows 10 this value can be used.
/// Windows Server 2003 and Windows XP: If the length of the formatted message exceeds 128K bytes, then FormatMessage will not
/// automatically fail with an error of ERROR_MORE_DATA.Windows 10: LocalAlloc() has different options: LMEM_FIXED, and LMEM_MOVABLE.
/// FormatMessage() uses LMEM_FIXED, so HeapFree can be used. If LMEM_MOVABLE is used, HeapFree cannot be used.
2018-05-13 23:41:49 -04:00
/// </term>
/// </item>
/// <item>
/// <term>FORMAT_MESSAGE_ARGUMENT_ARRAY0x00002000</term>
/// <term>
2018-10-26 14:24:07 -04:00
/// The Arguments parameter is not a va_list structure, but is a pointer to an array of values that represent the arguments.This flag
/// cannot be used with 64-bit integer values. If you are using a 64-bit integer, you must use the va_list structure.
2018-05-13 23:41:49 -04:00
/// </term>
/// </item>
/// <item>
/// <term>FORMAT_MESSAGE_FROM_HMODULE0x00000800</term>
/// <term>
2018-10-26 14:24:07 -04:00
/// The lpSource parameter is a module handle containing the message-table resource(s) to search. If this lpSource handle is NULL,
2018-11-28 14:33:55 -05:00
/// the current process's application image file will be searched. This flag cannot be used with FORMAT_MESSAGE_FROM_STRING.If the
/// module has no message table resource, the function fails with ERROR_RESOURCE_TYPE_NOT_FOUND.
2018-05-13 23:41:49 -04:00
/// </term>
/// </item>
/// <item>
/// <term>FORMAT_MESSAGE_FROM_STRING0x00000400</term>
/// <term>
2018-10-26 14:24:07 -04:00
/// The lpSource parameter is a pointer to a null-terminated string that contains a message definition. The message definition may
/// contain insert sequences, just as the message text in a message table resource may. This flag cannot be used with
/// FORMAT_MESSAGE_FROM_HMODULE or FORMAT_MESSAGE_FROM_SYSTEM.
2018-05-13 23:41:49 -04:00
/// </term>
/// </item>
/// <item>
/// <term>FORMAT_MESSAGE_FROM_SYSTEM0x00001000</term>
/// <term>
/// The function should search the system message-table resource(s) for the requested message. If this flag is specified with
2018-10-26 14:24:07 -04:00
/// FORMAT_MESSAGE_FROM_HMODULE, the function searches the system message table if the message is not found in the module specified
/// by lpSource. This flag cannot be used with FORMAT_MESSAGE_FROM_STRING.If this flag is specified, an application can pass the
/// result of the GetLastError function to retrieve the message text for a system-defined error.
2018-05-13 23:41:49 -04:00
/// </term>
/// </item>
/// <item>
/// <term>FORMAT_MESSAGE_IGNORE_INSERTS0x00000200</term>
/// <term>
2018-10-26 14:24:07 -04:00
/// Insert sequences in the message definition are to be ignored and passed through to the output buffer unchanged. This flag is
/// useful for fetching a message for later formatting. If this flag is set, the Arguments parameter is ignored.
2018-05-13 23:41:49 -04:00
/// </term>
/// </item>
/// </list>
/// </para>
/// <para>
2018-10-26 14:24:07 -04:00
/// The low-order byte of dwFlags can specify the maximum width of a formatted output line. The following are possible values of the
/// low-order byte.
2018-05-13 23:41:49 -04:00
/// </para>
/// <para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>0</term>
2018-10-26 14:24:07 -04:00
/// <term>
/// There are no output line width restrictions. The function stores line breaks that are in the message definition text into the
/// output buffer.
/// </term>
2018-05-13 23:41:49 -04:00
/// </item>
/// <item>
/// <term>FORMAT_MESSAGE_MAX_WIDTH_MASK0x000000FF</term>
/// <term>
2018-10-26 14:24:07 -04:00
/// The function ignores regular line breaks in the message definition text. The function stores hard-coded line breaks in the
/// message definition text into the output buffer. The function generates no new line breaks.
2018-05-13 23:41:49 -04:00
/// </term>
/// </item>
/// </list>
/// </para>
/// <para>
2018-10-26 14:24:07 -04:00
/// If the low-order byte is a nonzero value other than <c>FORMAT_MESSAGE_MAX_WIDTH_MASK</c>, it specifies the maximum number of
/// characters in an output line. The function ignores regular line breaks in the message definition text. The function never splits
/// a string delimited by white space across a line break. The function stores hard-coded line breaks in the message definition text
/// into the output buffer. Hard-coded line breaks are coded with the %n escape sequence.
2018-05-13 23:41:49 -04:00
/// </para>
/// </param>
/// <param name="lpSource">
/// <para>The location of the message definition. The type of this parameter depends upon the settings in the dwFlags parameter.</para>
/// <para>
/// <list type="table">
/// <listheader>
/// <term>dwFlags Setting</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>FORMAT_MESSAGE_FROM_HMODULE0x00000800</term>
/// <term>A handle to the module that contains the message table to search.</term>
/// </item>
/// <item>
/// <term>FORMAT_MESSAGE_FROM_STRING0x00000400</term>
/// <term>Pointer to a string that consists of unformatted message text. It will be scanned for inserts and formatted accordingly.</term>
/// </item>
/// </list>
/// </para>
/// <para>If neither of these flags is set in dwFlags, then lpSource is ignored.</para>
/// </param>
/// <param name="dwMessageId">The message identifier for the requested message. This parameter is ignored if dwFlags includes <c>FORMAT_MESSAGE_FROM_STRING</c>.</param>
/// <param name="dwLanguageId">
/// <para>The language identifier for the requested message. This parameter is ignored if dwFlags includes <c>FORMAT_MESSAGE_FROM_STRING</c>.</para>
/// <para>
2018-10-26 14:24:07 -04:00
/// If you pass a specific <c>LANGID</c> in this parameter, <c>FormatMessage</c> will return a message for that <c>LANGID</c> only.
/// If the function cannot find a message for that <c>LANGID</c>, it sets Last-Error to <c>ERROR_RESOURCE_LANG_NOT_FOUND</c>. If you
/// pass in zero, <c>FormatMessage</c> looks for a message for <c>LANGIDs</c> in the following order:
2018-05-13 23:41:49 -04:00
/// </para>
/// <para>
2018-10-26 14:24:07 -04:00
/// If <c>FormatMessage</c> does not locate a message for any of the preceding <c>LANGIDs</c>, it returns any language message string
/// that is present. If that fails, it returns <c>ERROR_RESOURCE_LANG_NOT_FOUND</c>.
2018-05-13 23:41:49 -04:00
/// </para>
/// </param>
/// <param name="lpBuffer">
/// <para>
/// A pointer to a buffer that receives the null-terminated string that specifies the formatted message. If dwFlags includes
2018-10-26 14:24:07 -04:00
/// <c>FORMAT_MESSAGE_ALLOCATE_BUFFER</c>, the function allocates a buffer using the <c>LocalAlloc</c> function, and places the
/// pointer to the buffer at the address specified in lpBuffer.
2018-05-13 23:41:49 -04:00
/// </para>
/// <para>This buffer cannot be larger than 64K bytes.</para>
/// </param>
/// <param name="nSize">
/// <para>
2018-10-26 14:24:07 -04:00
/// If the <c>FORMAT_MESSAGE_ALLOCATE_BUFFER</c> flag is not set, this parameter specifies the size of the output buffer, in
/// <c>TCHARs</c>. If <c>FORMAT_MESSAGE_ALLOCATE_BUFFER</c> is set, this parameter specifies the minimum number of <c>TCHARs</c> to
/// allocate for an output buffer.
2018-05-13 23:41:49 -04:00
/// </para>
/// <para>The output buffer cannot be larger than 64K bytes.</para>
/// </param>
/// <param name="Arguments">
/// <para>
2018-10-26 14:24:07 -04:00
/// An array of values that are used as insert values in the formatted message. A %1 in the format string indicates the first value
/// in the Arguments array; a %2 indicates the second argument; and so on.
2018-05-13 23:41:49 -04:00
/// </para>
/// <para>
2018-10-26 14:24:07 -04:00
/// The interpretation of each value depends on the formatting information associated with the insert in the message definition. The
/// default is to treat each value as a pointer to a null-terminated string.
2018-05-13 23:41:49 -04:00
/// </para>
/// <para>
2018-10-26 14:24:07 -04:00
/// By default, the Arguments parameter is of type <c>va_list*</c>, which is a language- and implementation-specific data type for
/// describing a variable number of arguments. The state of the <c>va_list</c> argument is undefined upon return from the function.
/// To use the <c>va_list</c> again, destroy the variable argument list pointer using <c>va_end</c> and reinitialize it with <c>va_start</c>.
2018-05-13 23:41:49 -04:00
/// </para>
/// <para>
2018-10-26 14:24:07 -04:00
/// If you do not have a pointer of type <c>va_list*</c>, then specify the <c>FORMAT_MESSAGE_ARGUMENT_ARRAY</c> flag and pass a
/// pointer to an array of <c>DWORD_PTR</c> values; those values are input to the message formatted as the insert values. Each insert
/// must have a corresponding element in the array.
2018-05-13 23:41:49 -04:00
/// </para>
/// </param>
/// <returns>
2018-10-26 14:24:07 -04:00
/// <para>
/// If the function succeeds, the return value is the number of <c>TCHARs</c> stored in the output buffer, excluding the terminating
/// null character.
/// </para>
2018-05-13 23:41:49 -04:00
/// <para>If the function fails, the return value is zero. To get extended error information, call <c>GetLastError</c>.</para>
/// </returns>
2018-10-26 14:24:07 -04:00
// DWORD WINAPI FormatMessage( _In_ DWORD dwFlags, _In_opt_ LPCVOID lpSource, _In_ DWORD dwMessageId, _In_ DWORD dwLanguageId, _Out_
// LPTSTR lpBuffer, _In_ DWORD nSize, _In_opt_ va_list *Arguments); https://msdn.microsoft.com/en-us/library/windows/desktop/ms679351(v=vs.85).aspx
2018-05-13 23:41:49 -04:00
[DllImport(Lib.Kernel32, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("WinBase.h", MSDNShortId = "ms679351")]
public static extern int FormatMessage(FormatMessageFlags dwFlags, HINSTANCE lpSource, uint dwMessageId, uint dwLanguageId, StringBuilder lpBuffer, uint nSize, IntPtr Arguments);
2018-05-13 23:41:49 -04:00
/// <summary>
2018-10-26 14:24:07 -04:00
/// Formats a message string. The function requires a message definition as input. The message definition can come from a buffer
/// passed into the function. It can come from a message table resource in an already-loaded module. Or the caller can ask the
/// function to search the system's message table resource(s) for the message definition. The function finds the message definition
/// in a message table resource based on a message identifier and a language identifier. The function copies the formatted message
/// text to an output buffer, processing any embedded insert sequences if requested.
2018-05-13 23:41:49 -04:00
/// </summary>
/// <param name="dwFlags">
/// <para>
2018-10-26 14:24:07 -04:00
/// The formatting options, and how to interpret the lpSource parameter. The low-order byte of dwFlags specifies how the function
/// handles line breaks in the output buffer. The low-order byte can also specify the maximum width of a formatted output line.
2018-05-13 23:41:49 -04:00
/// </para>
/// <para>This parameter can be one or more of the following values.</para>
/// <para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>FORMAT_MESSAGE_ALLOCATE_BUFFER0x00000100</term>
/// <term>
2018-10-26 14:24:07 -04:00
/// The function allocates a buffer large enough to hold the formatted message, and places a pointer to the allocated buffer at the
/// address specified by lpBuffer. The lpBuffer parameter is a pointer to an LPTSTR; you must cast the pointer to an LPTSTR (for
/// example, ). The nSize parameter specifies the minimum number of TCHARs to allocate for an output message buffer. The caller
/// should use the LocalFree function to free the buffer when it is no longer needed.If the length of the formatted message exceeds
/// 128K bytes, then FormatMessage will fail and a subsequent call to GetLastError will return ERROR_MORE_DATA.In previous versions
/// of Windows, this value was not available for use when compiling Windows Store apps. As of Windows 10 this value can be used.
/// Windows Server 2003 and Windows XP: If the length of the formatted message exceeds 128K bytes, then FormatMessage will not
/// automatically fail with an error of ERROR_MORE_DATA.Windows 10: LocalAlloc() has different options: LMEM_FIXED, and LMEM_MOVABLE.
/// FormatMessage() uses LMEM_FIXED, so HeapFree can be used. If LMEM_MOVABLE is used, HeapFree cannot be used.
2018-05-13 23:41:49 -04:00
/// </term>
/// </item>
/// <item>
/// <term>FORMAT_MESSAGE_ARGUMENT_ARRAY0x00002000</term>
/// <term>
2018-10-26 14:24:07 -04:00
/// The Arguments parameter is not a va_list structure, but is a pointer to an array of values that represent the arguments.This flag
/// cannot be used with 64-bit integer values. If you are using a 64-bit integer, you must use the va_list structure.
2018-05-13 23:41:49 -04:00
/// </term>
/// </item>
/// <item>
/// <term>FORMAT_MESSAGE_FROM_HMODULE0x00000800</term>
/// <term>
2018-10-26 14:24:07 -04:00
/// The lpSource parameter is a module handle containing the message-table resource(s) to search. If this lpSource handle is NULL,
2018-11-28 14:33:55 -05:00
/// the current process's application image file will be searched. This flag cannot be used with FORMAT_MESSAGE_FROM_STRING.If the
/// module has no message table resource, the function fails with ERROR_RESOURCE_TYPE_NOT_FOUND.
2018-05-13 23:41:49 -04:00
/// </term>
/// </item>
/// <item>
/// <term>FORMAT_MESSAGE_FROM_STRING0x00000400</term>
/// <term>
2018-10-26 14:24:07 -04:00
/// The lpSource parameter is a pointer to a null-terminated string that contains a message definition. The message definition may
/// contain insert sequences, just as the message text in a message table resource may. This flag cannot be used with
/// FORMAT_MESSAGE_FROM_HMODULE or FORMAT_MESSAGE_FROM_SYSTEM.
2018-05-13 23:41:49 -04:00
/// </term>
/// </item>
/// <item>
/// <term>FORMAT_MESSAGE_FROM_SYSTEM0x00001000</term>
/// <term>
/// The function should search the system message-table resource(s) for the requested message. If this flag is specified with
2018-10-26 14:24:07 -04:00
/// FORMAT_MESSAGE_FROM_HMODULE, the function searches the system message table if the message is not found in the module specified
/// by lpSource. This flag cannot be used with FORMAT_MESSAGE_FROM_STRING.If this flag is specified, an application can pass the
/// result of the GetLastError function to retrieve the message text for a system-defined error.
2018-05-13 23:41:49 -04:00
/// </term>
/// </item>
/// <item>
/// <term>FORMAT_MESSAGE_IGNORE_INSERTS0x00000200</term>
/// <term>
2018-10-26 14:24:07 -04:00
/// Insert sequences in the message definition are to be ignored and passed through to the output buffer unchanged. This flag is
/// useful for fetching a message for later formatting. If this flag is set, the Arguments parameter is ignored.
2018-05-13 23:41:49 -04:00
/// </term>
/// </item>
/// </list>
/// </para>
/// <para>
2018-10-26 14:24:07 -04:00
/// The low-order byte of dwFlags can specify the maximum width of a formatted output line. The following are possible values of the
/// low-order byte.
2018-05-13 23:41:49 -04:00
/// </para>
/// <para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>0</term>
2018-10-26 14:24:07 -04:00
/// <term>
/// There are no output line width restrictions. The function stores line breaks that are in the message definition text into the
/// output buffer.
/// </term>
2018-05-13 23:41:49 -04:00
/// </item>
/// <item>
/// <term>FORMAT_MESSAGE_MAX_WIDTH_MASK0x000000FF</term>
/// <term>
2018-10-26 14:24:07 -04:00
/// The function ignores regular line breaks in the message definition text. The function stores hard-coded line breaks in the
/// message definition text into the output buffer. The function generates no new line breaks.
2018-05-13 23:41:49 -04:00
/// </term>
/// </item>
/// </list>
/// </para>
/// <para>
2018-10-26 14:24:07 -04:00
/// If the low-order byte is a nonzero value other than <c>FORMAT_MESSAGE_MAX_WIDTH_MASK</c>, it specifies the maximum number of
/// characters in an output line. The function ignores regular line breaks in the message definition text. The function never splits
/// a string delimited by white space across a line break. The function stores hard-coded line breaks in the message definition text
/// into the output buffer. Hard-coded line breaks are coded with the %n escape sequence.
2018-05-13 23:41:49 -04:00
/// </para>
/// </param>
/// <param name="lpSource">
/// <para>The location of the message definition. The type of this parameter depends upon the settings in the dwFlags parameter.</para>
/// <para>
/// <list type="table">
/// <listheader>
/// <term>dwFlags Setting</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>FORMAT_MESSAGE_FROM_HMODULE0x00000800</term>
/// <term>A handle to the module that contains the message table to search.</term>
/// </item>
/// <item>
/// <term>FORMAT_MESSAGE_FROM_STRING0x00000400</term>
/// <term>Pointer to a string that consists of unformatted message text. It will be scanned for inserts and formatted accordingly.</term>
/// </item>
/// </list>
/// </para>
/// <para>If neither of these flags is set in dwFlags, then lpSource is ignored.</para>
/// </param>
/// <param name="dwMessageId">The message identifier for the requested message. This parameter is ignored if dwFlags includes <c>FORMAT_MESSAGE_FROM_STRING</c>.</param>
/// <param name="dwLanguageId">
/// <para>The language identifier for the requested message. This parameter is ignored if dwFlags includes <c>FORMAT_MESSAGE_FROM_STRING</c>.</para>
/// <para>
2018-10-26 14:24:07 -04:00
/// If you pass a specific <c>LANGID</c> in this parameter, <c>FormatMessage</c> will return a message for that <c>LANGID</c> only.
/// If the function cannot find a message for that <c>LANGID</c>, it sets Last-Error to <c>ERROR_RESOURCE_LANG_NOT_FOUND</c>. If you
/// pass in zero, <c>FormatMessage</c> looks for a message for <c>LANGIDs</c> in the following order:
2018-05-13 23:41:49 -04:00
/// </para>
/// <para>
2018-10-26 14:24:07 -04:00
/// If <c>FormatMessage</c> does not locate a message for any of the preceding <c>LANGIDs</c>, it returns any language message string
/// that is present. If that fails, it returns <c>ERROR_RESOURCE_LANG_NOT_FOUND</c>.
2018-05-13 23:41:49 -04:00
/// </para>
/// </param>
/// <param name="lpBuffer">
/// <para>
/// A pointer to a buffer that receives the null-terminated string that specifies the formatted message. If dwFlags includes
2018-10-26 14:24:07 -04:00
/// <c>FORMAT_MESSAGE_ALLOCATE_BUFFER</c>, the function allocates a buffer using the <c>LocalAlloc</c> function, and places the
/// pointer to the buffer at the address specified in lpBuffer.
2018-05-13 23:41:49 -04:00
/// </para>
/// <para>This buffer cannot be larger than 64K bytes.</para>
/// </param>
/// <param name="nSize">
/// <para>
2018-10-26 14:24:07 -04:00
/// If the <c>FORMAT_MESSAGE_ALLOCATE_BUFFER</c> flag is not set, this parameter specifies the size of the output buffer, in
/// <c>TCHARs</c>. If <c>FORMAT_MESSAGE_ALLOCATE_BUFFER</c> is set, this parameter specifies the minimum number of <c>TCHARs</c> to
/// allocate for an output buffer.
2018-05-13 23:41:49 -04:00
/// </para>
/// <para>The output buffer cannot be larger than 64K bytes.</para>
/// </param>
/// <param name="Arguments">
/// <para>
2018-10-26 14:24:07 -04:00
/// An array of values that are used as insert values in the formatted message. A %1 in the format string indicates the first value
/// in the Arguments array; a %2 indicates the second argument; and so on.
2018-05-13 23:41:49 -04:00
/// </para>
/// <para>
2018-10-26 14:24:07 -04:00
/// The interpretation of each value depends on the formatting information associated with the insert in the message definition. The
/// default is to treat each value as a pointer to a null-terminated string.
2018-05-13 23:41:49 -04:00
/// </para>
/// <para>
2018-10-26 14:24:07 -04:00
/// By default, the Arguments parameter is of type <c>va_list*</c>, which is a language- and implementation-specific data type for
/// describing a variable number of arguments. The state of the <c>va_list</c> argument is undefined upon return from the function.
/// To use the <c>va_list</c> again, destroy the variable argument list pointer using <c>va_end</c> and reinitialize it with <c>va_start</c>.
2018-05-13 23:41:49 -04:00
/// </para>
/// <para>
2018-10-26 14:24:07 -04:00
/// If you do not have a pointer of type <c>va_list*</c>, then specify the <c>FORMAT_MESSAGE_ARGUMENT_ARRAY</c> flag and pass a
/// pointer to an array of <c>DWORD_PTR</c> values; those values are input to the message formatted as the insert values. Each insert
/// must have a corresponding element in the array.
2018-05-13 23:41:49 -04:00
/// </para>
/// </param>
/// <returns>
2018-10-26 14:24:07 -04:00
/// <para>
/// If the function succeeds, the return value is the number of <c>TCHARs</c> stored in the output buffer, excluding the terminating
/// null character.
/// </para>
2018-05-13 23:41:49 -04:00
/// <para>If the function fails, the return value is zero. To get extended error information, call <c>GetLastError</c>.</para>
/// </returns>
2018-10-26 14:24:07 -04:00
// DWORD WINAPI FormatMessage( _In_ DWORD dwFlags, _In_opt_ LPCVOID lpSource, _In_ DWORD dwMessageId, _In_ DWORD dwLanguageId, _Out_
// LPTSTR lpBuffer, _In_ DWORD nSize, _In_opt_ va_list *Arguments); https://msdn.microsoft.com/en-us/library/windows/desktop/ms679351(v=vs.85).aspx
[DllImport(Lib.Kernel32, SetLastError = true, CharSet = CharSet.Auto)]
2018-05-13 23:41:49 -04:00
[PInvokeData("WinBase.h", MSDNShortId = "ms679351")]
public static extern int FormatMessage(FormatMessageFlags dwFlags, string lpSource, uint dwMessageId, uint dwLanguageId, StringBuilder lpBuffer, uint nSize, IntPtr Arguments);
2018-05-13 23:41:49 -04:00
/// <summary>
2018-10-26 14:24:07 -04:00
/// Formats a message string. The function requires a message definition as input. The message definition can come from a message
/// table resource in an already-loaded module. Or the caller can ask the function to search the system's message table resource(s)
/// for the message definition. The function finds the message definition in a message table resource based on a message identifier
/// and a language identifier. The function returns the formatted message text, processing any embedded insert sequences if requested.
2018-05-13 23:41:49 -04:00
/// </summary>
/// <param name="id">The message identifier for the requested message.</param>
/// <param name="args">
2018-10-26 14:24:07 -04:00
/// An array of values that are used as insert values in the formatted message. A %1 in the format string indicates the first value
/// in the Arguments array; a %2 indicates the second argument; and so on. The interpretation of each value depends on the formatting
/// information associated with the insert in the message definition. Each insert must have a corresponding element in the array.
2018-05-13 23:41:49 -04:00
/// </param>
/// <param name="hLib">A handle to the module that contains the message table to search.</param>
/// <param name="flags">
2018-10-26 14:24:07 -04:00
/// The formatting options, and how to interpret the lpSource parameter. The low-order byte of dwFlags specifies how the function
/// handles line breaks in the output buffer. The low-order byte can also specify the maximum width of a formatted output line.
2018-05-13 23:41:49 -04:00
/// </param>
/// <param name="langId">
2018-10-26 14:24:07 -04:00
/// The language identifier for the requested message. If you pass a specific LANGID in this parameter, FormatMessage will return a
/// message for that LANGID only. If the function cannot find a message for that LANGID, it sets Last-Error to
/// ERROR_RESOURCE_LANG_NOT_FOUND. If you pass in zero, FormatMessage looks for a message for LANGIDs in the following order:
/// Language neutral Thread LANGID, based on the thread's locale value User default LANGID, based on the user's default locale value
/// System default LANGID, based on the system default locale value US English If FormatMessage does not locate a message for any of
/// the preceding LANGIDs, it returns any language message string that is present. If that fails, it returns ERROR_RESOURCE_LANG_NOT_FOUND.
2018-05-13 23:41:49 -04:00
/// </param>
/// <returns>
2018-10-26 14:24:07 -04:00
/// If the function succeeds, the return value is the string that specifies the formatted message. To get extended error information,
/// call GetLastError.
2018-05-13 23:41:49 -04:00
/// </returns>
[PInvokeData("WinBase.h", MSDNShortId = "ms679351")]
public static string FormatMessage(uint id, object[] args = null, HINSTANCE hLib = default, FormatMessageFlags flags = 0, uint langId = 0)
2018-05-13 23:41:49 -04:00
{
flags &= ~FormatMessageFlags.FORMAT_MESSAGE_FROM_STRING;
flags |= FormatMessageFlags.FORMAT_MESSAGE_FROM_SYSTEM;
2018-10-26 14:24:07 -04:00
if (!hLib.IsNull) flags |= FormatMessageFlags.FORMAT_MESSAGE_FROM_HMODULE;
if (args != null && args.Length > 0)
{
if (!flags.IsFlagSet(FormatMessageFlags.FORMAT_MESSAGE_IGNORE_INSERTS)) flags |= FormatMessageFlags.FORMAT_MESSAGE_ARGUMENT_ARRAY;
args = Array.ConvertAll(args, o => o is int || o is uint ? (IntPtr)unchecked((int)o) : o);
}
Win32Error lastError;
var buf = new StringBuilder(1024);
using (var pargs = new SafeHGlobalHandle(args.MarshalObjectsToPtr(Marshal.AllocHGlobal, out var sz), sz, true))
do
{
if (0 != FormatMessage(flags, hLib, id, langId, buf, (uint)buf.Capacity, (IntPtr)pargs))
return buf.ToString();
else if (Win32Error.ERROR_INSUFFICIENT_BUFFER != (lastError = Marshal.GetLastWin32Error()))
lastError.ThrowIfFailed();
buf.Capacity = buf.Capacity * 2;
} while (true);
2018-05-13 23:41:49 -04:00
}
/// <summary>
2018-10-26 14:24:07 -04:00
/// Formats a message string. The function requires a message definition as input. The message definition can come from a message
/// table resource in an already-loaded module. Or the caller can ask the function to search the system's message table resource(s)
/// for the message definition. The function finds the message definition in a message table resource based on a message identifier
/// and a language identifier. The function returns the formatted message text, processing any embedded insert sequences if requested.
2018-05-13 23:41:49 -04:00
/// </summary>
2018-10-26 14:24:07 -04:00
/// <param name="formatString">
/// Pointer to a string that consists of unformatted message text. It will be scanned for inserts and formatted accordingly.
/// </param>
2018-05-13 23:41:49 -04:00
/// <param name="args">
2018-10-26 14:24:07 -04:00
/// An array of values that are used as insert values in the formatted message. A %1 in the format string indicates the first value
/// in the Arguments array; a %2 indicates the second argument; and so on. The interpretation of each value depends on the formatting
/// information associated with the insert in the message definition. Each insert must have a corresponding element in the array.
2018-05-13 23:41:49 -04:00
/// </param>
/// <param name="flags">
2018-10-26 14:24:07 -04:00
/// The formatting options, and how to interpret the lpSource parameter. The low-order byte of dwFlags specifies how the function
/// handles line breaks in the output buffer. The low-order byte can also specify the maximum width of a formatted output line.
2018-05-13 23:41:49 -04:00
/// </param>
/// <returns>
2018-10-26 14:24:07 -04:00
/// If the function succeeds, the return value is the string that specifies the formatted message. To get extended error information,
/// call GetLastError.
2018-05-13 23:41:49 -04:00
/// </returns>
[PInvokeData("WinBase.h", MSDNShortId = "ms679351")]
public static string FormatMessage(string formatString, object[] args, FormatMessageFlags flags = 0)
2018-05-13 23:41:49 -04:00
{
if (string.IsNullOrEmpty(formatString) || args == null || args.Length == 0 || flags.IsFlagSet(FormatMessageFlags.FORMAT_MESSAGE_IGNORE_INSERTS)) return formatString;
flags &= ~(FormatMessageFlags.FORMAT_MESSAGE_FROM_HMODULE | FormatMessageFlags.FORMAT_MESSAGE_FROM_SYSTEM);
flags |= FormatMessageFlags.FORMAT_MESSAGE_FROM_STRING | FormatMessageFlags.FORMAT_MESSAGE_ARGUMENT_ARRAY;
if (args != null && args.Length > 0)
args = Array.ConvertAll(args, o => o is int || o is uint ? (IntPtr)unchecked((int)o) : o);
Win32Error lastError;
var buf = new StringBuilder(1024);
using (var pargs = new SafeHGlobalHandle(args.MarshalObjectsToPtr(Marshal.AllocHGlobal, out var sz), sz, true))
do
{
if (0 != FormatMessage(flags, formatString, 0, 0, buf, (uint)buf.Capacity, (IntPtr)pargs))
return buf.ToString();
else if (Win32Error.ERROR_INSUFFICIENT_BUFFER != (lastError = Marshal.GetLastWin32Error()))
lastError.ThrowIfFailed();
buf.Capacity = buf.Capacity * 2;
} while (true);
2018-05-13 23:41:49 -04:00
}
/// <summary>Retrieves the error mode for the current process.</summary>
/// <returns>
/// <para>The process error mode. This function returns one of the following values.</para>
/// <para>
/// <list type="table">
/// <listheader>
/// <term>Return code/value</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>SEM_FAILCRITICALERRORS0x0001</term>
2018-10-26 14:24:07 -04:00
/// <term>
/// The system does not display the critical-error-handler message box. Instead, the system sends the error to the calling process.
/// </term>
2018-05-13 23:41:49 -04:00
/// </item>
/// <item>
/// <term>SEM_NOALIGNMENTFAULTEXCEPT0x0004</term>
/// <term>
2018-10-26 14:24:07 -04:00
/// The system automatically fixes memory alignment faults and makes them invisible to the application. It does this for the calling
/// process and any descendant processes. This feature is only supported by certain processor architectures. For more information,
/// see SetErrorMode.
2018-05-13 23:41:49 -04:00
/// </term>
/// </item>
/// <item>
/// <term>SEM_NOGPFAULTERRORBOX0x0002</term>
/// <term>The system does not display the Windows Error Reporting dialog.</term>
/// </item>
/// <item>
/// <term>SEM_NOOPENFILEERRORBOX0x8000</term>
2018-10-26 14:24:07 -04:00
/// <term>
/// The system does not display a message box when it fails to find a file. Instead, the error is returned to the calling process.
/// </term>
2018-05-13 23:41:49 -04:00
/// </item>
/// </list>
/// </para>
/// </returns>
// UINT WINAPI GetErrorMode(void); https://msdn.microsoft.com/en-us/library/windows/desktop/ms679355(v=vs.85).aspx
[DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("WinBase.h", MSDNShortId = "ms679355")]
public static extern uint GetErrorMode();
/// <summary>
/// <para>
2018-10-26 14:24:07 -04:00
/// Retrieves the calling thread's last-error code value. The last-error code is maintained on a per-thread basis. Multiple threads
/// do not overwrite each other's last-error code.
2018-05-13 23:41:49 -04:00
/// </para>
/// <para><c>Visual Basic:</c> Applications should call <c>err.LastDllError</c> instead of <c>GetLastError</c>.</para>
/// </summary>
/// <returns>
/// <para>The return value is the calling thread's last-error code.</para>
/// <para>
2018-10-26 14:24:07 -04:00
/// The Return Value section of the documentation for each function that sets the last-error code notes the conditions under which
/// the function sets the last-error code. Most functions that set the thread's last-error code set it when they fail. However, some
/// functions also set the last-error code when they succeed. If the function is not documented to set the last-error code, the value
/// returned by this function is simply the most recent last-error code to have been set; some functions set the last-error code to 0
/// on success and others do not.
2018-05-13 23:41:49 -04:00
/// </para>
/// </returns>
// DWORD WINAPI GetLastError(void);// https://msdn.microsoft.com/en-us/library/windows/desktop/ms679360(v=vs.85).aspx
[DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("WinBase.h", MSDNShortId = "ms679360")]
public static extern Win32Error GetLastError();
/// <summary>Retrieves the error mode for the calling thread.</summary>
/// <returns>
/// <para>The process error mode. This function returns one of the following values.</para>
/// <para>
/// <list type="table">
/// <listheader>
/// <term>Return code/value</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>SEM_FAILCRITICALERRORS = 0x0001</term>
2018-10-26 14:24:07 -04:00
/// <term>
/// The system does not display the critical-error-handler message box. Instead, the system sends the error to the calling process.
/// </term>
2018-05-13 23:41:49 -04:00
/// </item>
/// <item>
/// <term>SEM_NOGPFAULTERRORBOX = 0x0002</term>
/// <term>The system does not display the Windows Error Reporting dialog.</term>
/// </item>
/// <item>
/// <term>SEM_NOOPENFILEERRORBOX = 0x8000</term>
2018-10-26 14:24:07 -04:00
/// <term>
/// The system does not display a message box when it fails to find a file. Instead, the error is returned to the calling process.
/// </term>
2018-05-13 23:41:49 -04:00
/// </item>
/// </list>
/// </para>
/// </returns>
[DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("WinBase.h", MSDNShortId = "dd553629")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetThreadErrorMode(uint dwNewMode, out uint lpOldMode);
/// <summary>Raises an exception in the calling thread.</summary>
/// <param name="dwExceptionCode">
/// <para>
2018-10-26 14:24:07 -04:00
/// An application-defined exception code of the exception being raised. The filter expression and exception-handler block of an
/// exception handler can use the <c>GetExceptionCode</c> function to retrieve this value.
2018-05-13 23:41:49 -04:00
/// </para>
/// <para>
2018-10-26 14:24:07 -04:00
/// Note that the system will clear bit 28 of dwExceptionCode before displaying a message This bit is a reserved exception bit, used
/// by the system for its own purposes.
2018-05-13 23:41:49 -04:00
/// </para>
/// </param>
/// <param name="dwExceptionFlags">
2018-10-26 14:24:07 -04:00
/// The exception flags. This can be either zero to indicate a continuable exception, or EXCEPTION_NONCONTINUABLE to indicate a
/// noncontinuable exception. Any attempt to continue execution after a noncontinuable exception causes the
/// EXCEPTION_NONCONTINUABLE_EXCEPTION exception.
2018-05-13 23:41:49 -04:00
/// </param>
/// <param name="nNumberOfArguments">
2018-10-26 14:24:07 -04:00
/// The number of arguments in the lpArguments array. This value must not exceed EXCEPTION_MAXIMUM_PARAMETERS. This parameter is
/// ignored if lpArguments is <c>NULL</c>.
2018-05-13 23:41:49 -04:00
/// </param>
/// <param name="lpArguments">
2018-10-26 14:24:07 -04:00
/// An array of arguments. This parameter can be <c>NULL</c>. These arguments can contain any application-defined data that needs to
/// be passed to the filter expression of the exception handler.
2018-05-13 23:41:49 -04:00
/// </param>
/// <returns>This function does not return a value.</returns>
// void WINAPI RaiseException( _In_ DWORD dwExceptionCode, _In_ DWORD dwExceptionFlags, _In_ DWORD nNumberOfArguments, _In_ const ULONG_PTR
// *lpArguments); https://msdn.microsoft.com/en-us/library/windows/desktop/ms680552(v=vs.85).aspx
[DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("WinBase.h", MSDNShortId = "ms680552")]
public static extern void RaiseException(uint dwExceptionCode, EXCEPTION_FLAG dwExceptionFlags, uint nNumberOfArguments, [In] IntPtr lpArguments);
/// <summary>
2018-10-26 14:24:07 -04:00
/// Raises an exception that bypasses all exception handlers (frame or vector based). Raising this exception terminates the
/// application and invokes Windows Error Reporting, if Windows Error Reporting is enabled.
2018-05-13 23:41:49 -04:00
/// </summary>
/// <param name="pExceptionRecord">
/// <para>
2018-10-26 14:24:07 -04:00
/// A pointer to an <c>EXCEPTION_RECORD</c> structure that contains the exception information. You must specify the
/// <c>ExceptionAddress</c> and <c>ExceptionCode</c> members.
2018-05-13 23:41:49 -04:00
/// </para>
/// <para>
2018-10-26 14:24:07 -04:00
/// If this parameter is <c>NULL</c>, the function creates an exception record and sets the <c>ExceptionCode</c> member to
/// STATUS_FAIL_FAST_EXCEPTION. The function will also set the <c>ExceptionAddress</c> member if the dwFlags parameter contains the
/// FAIL_FAST_GENERATE_EXCEPTION_ADDRESS flag.
2018-05-13 23:41:49 -04:00
/// </para>
/// </param>
/// <param name="pContextRecord">
2018-10-26 14:24:07 -04:00
/// A pointer to a <c>CONTEXT</c> structure that contains the context information. If <c>NULL</c>, this function generates the
/// context (however, the context will not exactly match the context of the caller).
2018-05-13 23:41:49 -04:00
/// </param>
/// <param name="dwFlags">
/// <para>You can specify zero or the following flag that control this function's behavior:</para>
/// <para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>FAIL_FAST_GENERATE_EXCEPTION_ADDRESS0x1</term>
/// <term>
2018-10-26 14:24:07 -04:00
/// Causes RaiseFailFastException to set the ExceptionAddress of EXCEPTION_RECORD to the return address of this function (the next
/// instruction in the caller after the call to RaiseFailFastException). This function will set the exception address only if
/// ExceptionAddress is not NULL.
2018-05-13 23:41:49 -04:00
/// </term>
/// </item>
/// </list>
/// </para>
/// </param>
/// <returns>This function does not return a value.</returns>
2018-10-26 14:24:07 -04:00
// VOID WINAPI RaiseFailFastException( _In_opt_ PEXCEPTION_RECORD pExceptionRecord, _In_opt_ PCONTEXT pContextRecord, _In_ DWORD
// dwFlags); https://msdn.microsoft.com/en-us/library/windows/desktop/dd941688(v=vs.85).aspx
2018-05-13 23:41:49 -04:00
[DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("WinBase.h", MSDNShortId = "dd941688")]
public static extern void RaiseFailFastException(ref EXCEPTION_RECORD pExceptionRecord, IntPtr pContextRecord, FAIL_FAST_FLAGS dwFlags);
/// <summary>Unregisters a vectored continue handler.</summary>
2018-10-26 14:24:07 -04:00
/// <param name="Handler">
/// A pointer to a vectored exception handler previously registered using the <c>AddVectoredContinueHandler</c> function.
/// </param>
2018-05-13 23:41:49 -04:00
/// <returns>
/// <para>If the function succeeds, the return value is nonzero.</para>
/// <para>If the function fails, the return value is zero.</para>
/// </returns>
// ULONG WINAPI RemoveVectoredContinueHandler( _In_ PVOID Handler); https://msdn.microsoft.com/en-us/library/windows/desktop/ms680567(v=vs.85).aspx
[DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("WinBase.h", MSDNShortId = "ms680567")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool RemoveVectoredContinueHandler([In] IntPtr Handler);
/// <summary>Unregisters a vectored exception handler.</summary>
2018-10-26 14:24:07 -04:00
/// <param name="Handler">
/// A handle to the vectored exception handler previously registered using the <c>AddVectoredExceptionHandler</c> function.
/// </param>
2018-05-13 23:41:49 -04:00
/// <returns>
/// <para>If the function succeeds, the return value is nonzero.</para>
/// <para>If the function fails, the return value is zero.</para>
/// </returns>
// ULONG WINAPI RemoveVectoredExceptionHandler( _In_ PVOID Handler);
[DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("WinBase.h", MSDNShortId = "ms680571")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool RemoveVectoredExceptionHandler([In] IntPtr Handler);
/// <summary>Restores the last-error code for the calling thread.</summary>
/// <param name="dwErrCode">The last-error code for the thread.</param>
[DllImport(Lib.Kernel32, ExactSpelling = true, SetLastError = true)]
[PInvokeData("WinBase.h", MSDNShortId = "")]
public static extern void RestoreLastError(uint dwErrCode);
2018-10-26 14:24:07 -04:00
/// <summary>
/// Controls whether the system will handle the specified types of serious errors or whether the process will handle them.
/// </summary>
2018-05-13 23:41:49 -04:00
/// <param name="uMode">
/// <para>The process error mode. This parameter can be one or more of the following values.</para>
/// <para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>0</term>
/// <term>Use the system default, which is to display all error dialog boxes.</term>
/// </item>
/// <item>
/// <term>SEM_FAILCRITICALERRORS0x0001</term>
/// <term>
2018-10-26 14:24:07 -04:00
/// The system does not display the critical-error-handler message box. Instead, the system sends the error to the calling
/// process.Best practice is that all applications call the process-wide SetErrorMode function with a parameter of
/// SEM_FAILCRITICALERRORS at startup. This is to prevent error mode dialogs from hanging the application.
2018-05-13 23:41:49 -04:00
/// </term>
/// </item>
/// <item>
/// <term>SEM_NOALIGNMENTFAULTEXCEPT0x0004</term>
/// <term>
2018-10-26 14:24:07 -04:00
/// The system automatically fixes memory alignment faults and makes them invisible to the application. It does this for the calling
/// process and any descendant processes. This feature is only supported by certain processor architectures. For more information,
/// see the Remarks section. After this value is set for a process, subsequent attempts to clear the value are ignored.
2018-05-13 23:41:49 -04:00
/// </term>
/// </item>
/// <item>
/// <term>SEM_NOGPFAULTERRORBOX0x0002</term>
/// <term>The system does not display the Windows Error Reporting dialog.</term>
/// </item>
/// <item>
/// <term>SEM_NOOPENFILEERRORBOX0x8000</term>
/// <term>
2018-10-26 14:24:07 -04:00
/// The OpenFile function does not display a message box when it fails to find a file. Instead, the error is returned to the caller.
/// This error mode overrides the OF_PROMPT flag.
2018-05-13 23:41:49 -04:00
/// </term>
/// </item>
/// </list>
/// </para>
/// </param>
/// <returns>The return value is the previous state of the error-mode bit flags.</returns>
// UINT WINAPI SetErrorMode( _In_ UINT uMode); https://msdn.microsoft.com/en-us/library/windows/desktop/ms680621(v=vs.85).aspx
[DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("WinBase.h", MSDNShortId = "ms680621")]
public static extern uint SetErrorMode(uint uMode);
/// <summary>Sets the last-error code for the calling thread.</summary>
/// <param name="dwErrCode">The last-error code for the thread.</param>
[DllImport(Lib.Kernel32, ExactSpelling = true, SetLastError = true)]
[PInvokeData("WinBase.h", MSDNShortId = "ms680627")]
public static extern void SetLastError(uint dwErrCode);
2018-10-26 14:24:07 -04:00
/// <summary>
/// Controls whether the system will handle the specified types of serious errors or whether the calling thread will handle them.
/// </summary>
2018-05-13 23:41:49 -04:00
/// <param name="dwNewMode">
/// <para>The thread error mode. This parameter can be one or more of the following values.</para>
/// <para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>0</term>
/// <term>Use the system default, which is to display all error dialog boxes.</term>
/// </item>
/// <item>
/// <term>SEM_FAILCRITICALERRORS0x0001</term>
/// <term>
2018-10-26 14:24:07 -04:00
/// The system does not display the critical-error-handler message box. Instead, the system sends the error to the calling
/// thread.Best practice is that all applications call the process-wide SetErrorMode function with a parameter of
/// SEM_FAILCRITICALERRORS at startup. This is to prevent error mode dialogs from hanging the application.
2018-05-13 23:41:49 -04:00
/// </term>
/// </item>
/// <item>
/// <term>SEM_NOGPFAULTERRORBOX0x0002</term>
/// <term>The system does not display the Windows Error Reporting dialog.</term>
/// </item>
/// <item>
/// <term>SEM_NOOPENFILEERRORBOX0x8000</term>
/// <term>
2018-10-26 14:24:07 -04:00
/// The OpenFile function does not display a message box when it fails to find a file. Instead, the error is returned to the caller.
/// This error mode overrides the OF_PROMPT flag.
2018-05-13 23:41:49 -04:00
/// </term>
/// </item>
/// </list>
/// </para>
/// </param>
2018-10-26 14:24:07 -04:00
/// <param name="lpOldMode">
/// If the function succeeds, this parameter is set to the thread's previous error mode. This parameter can be <c>NULL</c>.
/// </param>
2018-05-13 23:41:49 -04:00
/// <returns>
/// <para>If the function succeeds, the return value is nonzero.</para>
/// <para>If the function fails, the return value is zero. To get extended error information, call <c>GetLastError</c>.</para>
/// </returns>
// BOOL SetThreadErrorMode( _In_ DWORD dwNewMode, _Out_ LPDWORD lpOldMode); https://msdn.microsoft.com/en-us/library/windows/desktop/dd553630(v=vs.85).aspx
[DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)]
[PInvokeData("WinBase.h", MSDNShortId = "dd553630")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetThreadErrorMode(uint dwNewMode, out uint lpOldMode);
/// <summary>
/// <para>Enables an application to supersede the top-level exception handler of each thread of a process.</para>
/// <para>
2018-10-26 14:24:07 -04:00
/// After calling this function, if an exception occurs in a process that is not being debugged, and the exception makes it to the
/// unhandled exception filter, that filter will call the exception filter function specified by the lpTopLevelExceptionFilter parameter.
2018-05-13 23:41:49 -04:00
/// </para>
/// </summary>
/// <param name="lpTopLevelExceptionFilter">
/// <para>
2018-10-26 14:24:07 -04:00
/// A pointer to a top-level exception filter function that will be called whenever the <c>UnhandledExceptionFilter</c> function gets
/// control, and the process is not being debugged. A value of <c>NULL</c> for this parameter specifies default handling within <c>UnhandledExceptionFilter</c>.
2018-05-13 23:41:49 -04:00
/// </para>
/// <para>
2018-10-26 14:24:07 -04:00
/// The filter function has syntax similar to that of <c>UnhandledExceptionFilter</c>: It takes a single parameter of type
/// <c>LPEXCEPTION_POINTERS</c>, has a WINAPI calling convention, and returns a value of type <c>LONG</c>. The filter function should
/// return one of the following values.
2018-05-13 23:41:49 -04:00
/// </para>
/// <para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>EXCEPTION_EXECUTE_HANDLER0x1</term>
/// <term>Return from UnhandledExceptionFilter and execute the associated exception handler. This usually results in process termination.</term>
/// </item>
/// <item>
/// <term>EXCEPTION_CONTINUE_EXECUTION0xffffffff</term>
/// <term>
2018-10-26 14:24:07 -04:00
/// Return from UnhandledExceptionFilter and continue execution from the point of the exception. Note that the filter function is
/// free to modify the continuation state by modifying the exception information supplied through its LPEXCEPTION_POINTERS parameter.
2018-05-13 23:41:49 -04:00
/// </term>
/// </item>
/// <item>
/// <term>EXCEPTION_CONTINUE_SEARCH0x0</term>
/// <term>
2018-10-26 14:24:07 -04:00
/// Proceed with normal execution of UnhandledExceptionFilter. That means obeying the SetErrorMode flags, or invoking the Application
/// Error pop-up message box.
2018-05-13 23:41:49 -04:00
/// </term>
/// </item>
/// </list>
/// </para>
/// </param>
/// <returns>
2018-10-26 14:24:07 -04:00
/// The <c>SetUnhandledExceptionFilter</c> function returns the address of the previous exception filter established with the
/// function. A <c>NULL</c> return value means that there is no current top-level exception handler.
2018-05-13 23:41:49 -04:00
/// </returns>
// LPTOP_LEVEL_EXCEPTION_FILTER WINAPI SetUnhandledExceptionFilter( _In_ LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter); https://msdn.microsoft.com/en-us/library/windows/desktop/ms680634(v=vs.85).aspx
[DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("WinBase.h", MSDNShortId = "ms680634")]
public static extern PTOP_LEVEL_EXCEPTION_FILTER SetUnhandledExceptionFilter(PTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter);
/// <summary>Undocumented.</summary>
/// <param name="FailedAllocationSize">Size of the failed allocation.</param>
[DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("WinBase.h", MSDNShortId = "")]
public static extern void TerminateProcessOnMemoryExhaustion(SizeT FailedAllocationSize);
/// <summary>
2018-10-26 14:24:07 -04:00
/// An application-defined function that passes unhandled exceptions to the debugger, if the process is being debugged. Otherwise, it
/// optionally displays an <c>Application Error</c> message box and causes the exception handler to be executed. This function can be
/// called only from within the filter expression of an exception handler.
2018-05-13 23:41:49 -04:00
/// </summary>
/// <param name="ExceptionInfo">
2018-10-26 14:24:07 -04:00
/// A pointer to an <c>EXCEPTION_POINTERS</c> structure that specifies a description of the exception and the processor context at
/// the time of the exception. This pointer is the return value of a call to the <c>GetExceptionInformation</c> function.
2018-05-13 23:41:49 -04:00
/// </param>
/// <returns>
/// <para>The function returns one of the following values.</para>
/// <para>
/// <list type="table">
/// <listheader>
/// <term>Return code/value</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>EXCEPTION_CONTINUE_SEARCH0x0</term>
2018-10-26 14:24:07 -04:00
/// <term>The process is being debugged, so the exception should be passed (as second chance) to the application's debugger.</term>
2018-05-13 23:41:49 -04:00
/// </item>
/// <item>
/// <term>EXCEPTION_EXECUTE_HANDLER0x1</term>
/// <term>
2018-10-26 14:24:07 -04:00
/// If the SEM_NOGPFAULTERRORBOX flag was specified in a previous call to SetErrorMode, no Application Error message box is
/// displayed. The function returns control to the exception handler, which is free to take any appropriate action.
2018-05-13 23:41:49 -04:00
/// </term>
/// </item>
/// </list>
/// </para>
/// </returns>
// LONG WINAPI UnhandledExceptionFilter( _In_ struct _EXCEPTION_POINTERS *ExceptionInfo); https://msdn.microsoft.com/en-us/library/windows/desktop/ms681401(v=vs.85).aspx
[DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("WinBase.h", MSDNShortId = "ms681401")]
2018-10-26 14:24:07 -04:00
public static extern EXCEPTION_FLAG UnhandledExceptionFilter(in EXCEPTION_POINTERS ExceptionInfo);
2018-05-13 23:41:49 -04:00
/// <summary>
2018-10-26 14:24:07 -04:00
/// Contains an exception record with a machine-independent description of an exception and a context record with a machine-dependent
/// description of the processor context at the time of the exception.
2018-05-13 23:41:49 -04:00
/// </summary>
// typedef struct _EXCEPTION_POINTERS { PEXCEPTION_RECORD ExceptionRecord; PCONTEXT ContextRecord;} EXCEPTION_POINTERS, *PEXCEPTION_POINTERS;
[PInvokeData("WinNT.h", MSDNShortId = "ms679331")]
[StructLayout(LayoutKind.Sequential)]
public struct EXCEPTION_POINTERS
{
/// <summary>A pointer to an <c>EXCEPTION_RECORD</c> structure that contains a machine-independent description of the exception.</summary>
public IntPtr ExceptionRecord;
/// <summary>
2018-10-26 14:24:07 -04:00
/// A pointer to a <c>CONTEXT</c> structure that contains a processor-specific description of the state of the processor at the
/// time of the exception.
2018-05-13 23:41:49 -04:00
/// </summary>
public IntPtr ContextRecord;
}
/// <summary>Common Exception codes</summary>
/// <remarks>
/// Users can define their own exception codes, so the code could be any value. The OS reserves bit 28 and may clear that for its own purposes
/// </remarks>
public enum ExceptionCode : uint
{
None = 0x0,
STATUS_BREAKPOINT = 0x80000003,
STATUS_SINGLESTEP = 0x80000004,
EXCEPTION_INT_DIVIDE_BY_ZERO = 0xC0000094,
/// <summary>Fired when debuggee gets a Control-C.</summary>
DBG_CONTROL_C = 0x40010005,
EXCEPTION_STACK_OVERFLOW = 0xC00000FD,
EXCEPTION_NONCONTINUABLE_EXCEPTION = 0xC0000025,
EXCEPTION_ACCESS_VIOLATION = 0xc0000005,
}
2018-05-13 23:41:49 -04:00
/// <summary>Describes an exception.</summary>
2018-10-26 14:24:07 -04:00
// typedef struct _EXCEPTION_RECORD { DWORD ExceptionCode; DWORD ExceptionFlags; struct _EXCEPTION_RECORD *ExceptionRecord; PVOID
// ExceptionAddress; DWORD NumberParameters; ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];} EXCEPTION_RECORD, *PEXCEPTION_RECORD;
2018-05-13 23:41:49 -04:00
[PInvokeData("WinNT.h", MSDNShortId = "aa363082")]
[StructLayout(LayoutKind.Sequential)]
public struct EXCEPTION_RECORD
{
/// <summary>
2018-10-26 14:24:07 -04:00
/// The exception flags. This member can be either zero, indicating a continuable exception, or <c>EXCEPTION_NONCONTINUABLE</c>
/// indicating a noncontinuable exception. Any attempt to continue execution after a noncontinuable exception causes the
/// <c>EXCEPTION_NONCONTINUABLE_EXCEPTION</c> exception.
2018-05-13 23:41:49 -04:00
/// </summary>
public ExceptionCode ExceptionCode;
2018-05-13 23:41:49 -04:00
/// <summary>
2018-10-26 14:24:07 -04:00
/// The exception flags. This member can be either zero, indicating a continuable exception, or <c>EXCEPTION_NONCONTINUABLE</c>
/// indicating a noncontinuable exception. Any attempt to continue execution after a noncontinuable exception causes the
/// <c>EXCEPTION_NONCONTINUABLE_EXCEPTION</c> exception.
2018-05-13 23:41:49 -04:00
/// </summary>
public EXCEPTION_FLAG ExceptionFlags;
/// <summary>
2018-10-26 14:24:07 -04:00
/// A pointer to an associated <c>EXCEPTION_RECORD</c> structure. Exception records can be chained together to provide additional
/// information when nested exceptions occur.
2018-05-13 23:41:49 -04:00
/// </summary>
public IntPtr ExceptionRecord;
/// <summary>The address where the exception occurred.</summary>
public IntPtr ExceptionAddress;
/// <summary>
2018-10-26 14:24:07 -04:00
/// The number of parameters associated with the exception. This is the number of defined elements in the
/// <c>ExceptionInformation</c> array.
2018-05-13 23:41:49 -04:00
/// </summary>
public uint NumberParameters;
// From code at https://github.com/SymbolSource/Microsoft.Samples.Debugging/blob/master/src/debugger/NativeDebugWrappers/NativeImports.cs, it provides a work-around the problem a ByValArray causes when marshaling regarding alignment. It creates separate entries for each item in the array.
//[MarshalAs(UnmanagedType.ByValArray, SizeConst = EXCEPTION_MAXIMUM_PARAMETERS)]
//public IntPtr[] ExceptionInformation;
private IntPtr ExceptionInformation0;
private IntPtr ExceptionInformation1;
private IntPtr ExceptionInformation2;
private IntPtr ExceptionInformation3;
private IntPtr ExceptionInformation4;
private IntPtr ExceptionInformation5;
private IntPtr ExceptionInformation6;
private IntPtr ExceptionInformation7;
private IntPtr ExceptionInformation8;
private IntPtr ExceptionInformation9;
private IntPtr ExceptionInformation10;
private IntPtr ExceptionInformation11;
private IntPtr ExceptionInformation12;
private IntPtr ExceptionInformation13;
private IntPtr ExceptionInformation14;
/// <summary>
/// An associated <c>EXCEPTION_RECORD</c> structure. Exception records can be chained together to provide additional
/// information when nested exceptions occur.
/// </summary>
public EXCEPTION_RECORD? ChainedRecord => ExceptionRecord.ToNullableStructure<EXCEPTION_RECORD>();
2018-05-13 23:41:49 -04:00
/// <summary>
/// <para>
2018-10-26 14:24:07 -04:00
/// An array of additional arguments that describe the exception. The <c>RaiseException</c> function can specify this array of
/// arguments. For most exception codes, the array elements are undefined. The following table describes the exception codes
/// whose array elements are defined.
2018-05-13 23:41:49 -04:00
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Exception code</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>EXCEPTION_ACCESS_VIOLATION</term>
/// <term>
2018-10-26 14:24:07 -04:00
/// The first element of the array contains a read-write flag that indicates the type of operation that caused the access
/// violation. If this value is zero, the thread attempted to read the inaccessible data. If this value is 1, the thread
/// attempted to write to an inaccessible address. If this value is 8, the thread causes a user-mode data execution prevention
/// (DEP) violation.The second array element specifies the virtual address of the inaccessible data.
2018-05-13 23:41:49 -04:00
/// </term>
/// </item>
/// <item>
/// <term>EXCEPTION_IN_PAGE_ERROR</term>
/// <term>
2018-10-26 14:24:07 -04:00
/// The first element of the array contains a read-write flag that indicates the type of operation that caused the access
/// violation. If this value is zero, the thread attempted to read the inaccessible data. If this value is 1, the thread
/// attempted to write to an inaccessible address. If this value is 8, the thread causes a user-mode data execution prevention
/// (DEP) violation. The second array element specifies the virtual address of the inaccessible data.The third array element
/// specifies the underlying NTSTATUS code that resulted in the exception.
2018-05-13 23:41:49 -04:00
/// </term>
/// </item>
/// </list>
/// </summary>
public IntPtr[] ExceptionInformation
{
get => new[] { ExceptionInformation0, ExceptionInformation1, ExceptionInformation2, ExceptionInformation3, ExceptionInformation4, ExceptionInformation5, ExceptionInformation6, ExceptionInformation7, ExceptionInformation8, ExceptionInformation9, ExceptionInformation10, ExceptionInformation11, ExceptionInformation12, ExceptionInformation13, ExceptionInformation14 };
set
{
if (value is null || value.Length != EXCEPTION_MAXIMUM_PARAMETERS)
throw new ArgumentOutOfRangeException(nameof(value));
for (int i = 0; i < EXCEPTION_MAXIMUM_PARAMETERS; i++)
this.SetFieldValue($"ExceptionInformation{i}", value[i]);
}
}
2018-05-13 23:41:49 -04:00
}
/// <summary>A safe handle for continue handler handles.</summary>
/// <seealso cref="Vanara.InteropServices.GenericSafeHandle"/>
public class SafeContinueHandlerHandle : GenericSafeHandle
{
/// <summary>Initializes a new instance of the <see cref="SafeContinueHandlerHandle"/> class.</summary>
public SafeContinueHandlerHandle() : this(IntPtr.Zero) { }
/// <summary>Initializes a new instance of the <see cref="SafeContinueHandlerHandle"/> class.</summary>
/// <param name="handle">The handle.</param>
public SafeContinueHandlerHandle(IntPtr handle) : base(handle, RemoveVectoredContinueHandler) { }
}
/// <summary>A safe handle for exception handler handles.</summary>
/// <seealso cref="Vanara.InteropServices.GenericSafeHandle"/>
public class SafeExceptionHandlerHandle : GenericSafeHandle
{
/// <summary>Initializes a new instance of the <see cref="SafeExceptionHandlerHandle"/> class.</summary>
public SafeExceptionHandlerHandle() : this(IntPtr.Zero) { }
/// <summary>Initializes a new instance of the <see cref="SafeExceptionHandlerHandle"/> class.</summary>
/// <param name="handle">The handle.</param>
public SafeExceptionHandlerHandle(IntPtr handle) : base(handle, RemoveVectoredExceptionHandler) { }
}
}
}