using System; using System.Runtime.InteropServices; using Vanara.Extensions; using Vanara.InteropServices; using static Vanara.Extensions.BitHelper; namespace Vanara.PInvoke { public static partial class Kernel32 { /// public const uint ACL_REVISION = 2; /// public const uint ACL_REVISION_DS = 4; /// public const string OUT_OF_PROCESS_FUNCTION_TABLE_CALLBACK_EXPORT_NAME = "OutOfProcessFunctionTableCallback"; /// public const byte PERFORMANCE_DATA_VERSION = 1; /// Retrieves the function table entries for the functions in the specified region of memory. /// The control address. /// A pointer to the user-defined data to be passed from the function call. /// Pointer to a structure. [UnmanagedFunctionPointer(CallingConvention.Winapi)] [PInvokeData("WinNT.h")] public delegate IntPtr GetRuntimeFunctionCallback(IntPtr ControlPc, IntPtr Context); /// [UnmanagedFunctionPointer(CallingConvention.Winapi)] [PInvokeData("WinNT.h")] public delegate uint OutOfProcessFunctionTableCallback(HPROCESS Process, IntPtr TableAddress, out uint Entries, [Out] IMAGE_RUNTIME_FUNCTION_ENTRY[] Functions); /// /// The application-defined user-mode scheduling (UMS) scheduler entry point function associated with a UMS completion list. /// /// The PUMS_SCHEDULER_ENTRY_POINT type defines a pointer to this function. UmsSchedulerProc is a placeholder for the /// application-defined function name. /// /// /// /// The reason the scheduler entry point is being called. This parameter can be one of the following values. /// /// /// Value /// Meaning /// /// /// UmsSchedulerStartup 0 /// /// A UMS scheduler thread was created. The entry point is called with this reason once each time EnterUmsSchedulingMode is called. /// /// /// /// UmsSchedulerThreadBlocked 1 /// A UMS worker thread blocked. /// /// /// UmsSchedulerThreadYield 2 /// An executing UMS worker thread yielded control by calling the UmsThreadYield function. /// /// /// /// /// If the Reason parameter is UmsSchedulerStartup, this parameter is NULL. /// /// If the Reason parameter is UmsSchedulerThreadBlocked, bit 0 of this parameter indicates the type of activity that was /// being serviced when the UMS worker thread blocked. /// /// /// /// Value /// Meaning /// /// /// 0 /// /// The thread blocked on a trap (for example, a hard page fault) or an interrupt (for example, an asynchronous procedure call). /// /// /// /// 1 /// The thread blocked on a system call. /// /// /// /// If the Reason parameter is UmsSchedulerThreadYield, this parameter is a pointer to the UMS thread context of the UMS /// worker thread that yielded. /// /// /// /// /// If the Reason parameter is UmsSchedulerStartup, this parameter is the SchedulerParam member of the /// UMS_SCHEDULER_STARTUP_INFO structure passed to the EnterUmsSchedulingMode function that triggered the entry point call. /// /// /// If the Reason parameter is UmsSchedulerThreadYield this parameter is the SchedulerParam parameter passed to the /// UmsThreadYield function that triggered the entry point call. /// /// If the Reason parameter is UmsSchedulerThreadBlocked, this parameter is NULL. /// /// /// This function does not return a value. /// /// /// /// The UmsSchedulerProc function pointer type is defined as PUMS_SCHEDULER_ENTRY_POINT in WinBase.h. The underlying function /// type is defined as RTL_UMS_SCHEDULER_ENTRY_POINT in WinNT.h /// /// /// Each UMS scheduler thread has an associated UmsSchedulerProc entry point function that is specified when the thread calls the /// EnterUmsSchedulingMode function. The system calls the scheduler entry point function with a reason of UmsSchedulerStartup /// when the scheduler thread is converted for UMS. /// /// /// Subsequently, when a UMS worker thread that is running on the scheduler thread yields or blocks, the system calls the scheduler /// thread's entry point function with a pointer to the UMS thread context of the worker thread. /// /// /// The application's scheduler is responsible for selecting the next UMS worker thread to run. The scheduler implements all policies /// that influence execution of its UMS threads, including processor affinity and thread priority. For example, a scheduler might /// give priority to I/O-intensive threads, or it might run threads on a first-come, first-served basis. This logic can be /// implemented in the scheduler entry point function or elsewhere in the application. /// /// /// When a blocked UMS worker thread becomes unblocked, the system queues the unblocked thread to the associated completion list and /// signals the completion list event. To retrieve UMS worker threads from the completion list, use the DequeueUmsCompletionListItems function. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/winnt/nc-winnt-rtl_ums_scheduler_entry_point RTL_UMS_SCHEDULER_ENTRY_POINT // RtlUmsSchedulerEntryPoint; void RtlUmsSchedulerEntryPoint( RTL_UMS_SCHEDULER_REASON Reason, ULONG_PTR ActivationPayload, PVOID // SchedulerParam ) {...} [PInvokeData("winnt.h", MSDNShortId = "10de1c48-255d-45c3-acf0-25f8a564b585")] [UnmanagedFunctionPointer(CallingConvention.Winapi)] public delegate void RtlUmsSchedulerEntryPoint(RTL_UMS_SCHEDULER_REASON Reason, IntPtr ActivationPayload, IntPtr SchedulerParam); /// /// /// An application-defined function previously registered with the AddSecureMemoryCacheCallback function that is called when a /// secured memory range is freed or its protections are changed. /// /// /// The PSECURE_MEMORY_CACHE_CALLBACK type defines a pointer to this callback function. is a placeholder for the /// application-defined function name. /// /// /// /// The starting address of the memory range. /// /// /// The size of the memory range, in bytes. /// /// /// The return value indicates the success or failure of this function. /// If the caller has secured the specified memory range, this function should unsecure the memory and return TRUE. /// If the caller has not secured the specified memory range, this function should return FALSE. /// /// /// /// After the callback function is registered, it is called after any attempt to free the specified memory range or change its /// protections. If the application has secured any part of the specified memory range, the callback function must invalidate all of /// the application's cached memory mappings for the secured memory range, unsecure the secured parts of the memory range, and return /// TRUE. Otherwise it must return FALSE. /// /// /// The application secures and unsecures a memory range by sending requests to a device driver, which uses the MmSecureVirtualMemory /// and MmUnsecureVirtualMemory functions to actually secure and unsecure the range. Operations on other types of secured or locked /// memory do not trigger this callback. /// /// /// Examples of function calls that trigger the callback function include calls to the VirtualFree, VirtualFreeEx, VirtualProtect, /// VirtualProtectEx, and UnmapViewOfFile functions. /// /// /// The callback function can also be triggered by a heap operation. In this case, the function must not perform any further /// operations on the heap that triggered the callback. This includes calling heap functions on a private heap or the process's /// default heap, or calling standard library functions such as malloc and free, which implicitly use the process's /// default heap. /// /// To unregister the callback function, use the RemoveSecureMemoryCacheCallback function. /// // https://docs.microsoft.com/en-us/windows/desktop/api/winnt/nc-winnt-psecure_memory_cache_callback BOOLEAN // PsecureMemoryCacheCallback( PVOID Addr, SIZE_T Range ) {...} [UnmanagedFunctionPointer(CallingConvention.Winapi)] [PInvokeData("winnt.h", MSDNShortId = "abde4b6f-7cd8-4a4b-9b00-f035b2c29054")] [return: MarshalAs(UnmanagedType.U1)] public delegate bool SecureMemoryCacheCallback(IntPtr Addr, SizeT Range); /// The flags that control the enforcement of the minimum and maximum working set sizes. [PInvokeData("winnt.h")] [Flags] public enum QUOTA_LIMITS_HARDWS { /// The working set will not fall below the minimum working set limit. QUOTA_LIMITS_HARDWS_MIN_ENABLE = 0x00000001, /// The working set may fall below the minimum working set limit if memory demands are high. QUOTA_LIMITS_HARDWS_MIN_DISABLE = 0x00000002, /// The working set will not exceed the maximum working set limit. QUOTA_LIMITS_HARDWS_MAX_ENABLE = 0x00000004, /// The working set may exceed the maximum working set limit if there is abundant memory. QUOTA_LIMITS_HARDWS_MAX_DISABLE = 0x00000008, /// The quota limits use default limits QUOTA_LIMITS_USE_DEFAULT_LIMITS = 0x00000010, } /// Used by . [PInvokeData("winnt.h", MSDNShortId = "10de1c48-255d-45c3-acf0-25f8a564b585")] public enum RTL_UMS_SCHEDULER_REASON { /// /// A UMS scheduler thread was created. The entry point is called with this reason once each time EnterUmsSchedulingMode is called. /// UmsSchedulerStartup = 0, /// A UMS worker thread blocked. UmsSchedulerThreadBlocked = 1, /// An executing UMS worker thread yielded control by calling the UmsThreadYield function. UmsSchedulerThreadYield = 2, } /// /// Represents classes of information about user-mode scheduling (UMS) threads. /// This enumeration is used by the QueryUmsThreadInformation and SetUmsThreadInformation functions. /// // https://docs.microsoft.com/en-us/windows/desktop/api/winnt/ne-winnt-_rtl_ums_thread_info_class typedef enum // _RTL_UMS_THREAD_INFO_CLASS { UmsThreadInvalidInfoClass , UmsThreadUserContext , UmsThreadPriority , UmsThreadAffinity , // UmsThreadTeb , UmsThreadIsSuspended , UmsThreadIsTerminated , UmsThreadMaxInfoClass } RTL_UMS_THREAD_INFO_CLASS, *PRTL_UMS_THREAD_INFO_CLASS; [PInvokeData("winnt.h", MSDNShortId = "2d6730b2-4d01-45f5-9514-0d91806f50d5")] public enum RTL_UMS_THREAD_INFO_CLASS { /// Reserved. UmsThreadInvalidInfoClass, /// Application-defined information stored in a UMS thread context. [CorrespondingType(typeof(IntPtr))] UmsThreadUserContext, /// Reserved. UmsThreadPriority, /// Reserved. UmsThreadAffinity, /// /// The thread execution block (TEB) for a UMS thread. This information class can only be queried; it cannot be set. /// [CorrespondingType(typeof(IntPtr), CorrespondingAction.Get)] UmsThreadTeb, /// The suspension status of the thread. This information can only be queried; it cannot be set. [CorrespondingType(typeof(bool), CorrespondingAction.Get)] UmsThreadIsSuspended, /// The termination status of the thread. This information can only be queried; it cannot be set. [CorrespondingType(typeof(bool), CorrespondingAction.Get)] UmsThreadIsTerminated, /// Reserved. UmsThreadMaxInfoClass, } /// Section access rights. [PInvokeData("winnt.h")] [Flags] public enum SECTION_MAP : uint { /// Query the section object for information about the section. Drivers should set this flag. SECTION_QUERY = 0x0001, /// Write views of the section. SECTION_MAP_WRITE = 0x0002, /// Read views of the section. SECTION_MAP_READ = 0x0004, /// Execute views of the section. SECTION_MAP_EXECUTE = 0x0008, /// Dynamically extend the size of the section. SECTION_EXTEND_SIZE = 0x0010, /// Undocumented. SECTION_MAP_EXECUTE_EXPLICIT = 0x0020, /// All of the previous flags combined with STANDARD_RIGHTS_REQUIRED. SECTION_ALL_ACCESS = ACCESS_MASK.STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_WRITE | SECTION_MAP_READ | SECTION_MAP_EXECUTE | SECTION_EXTEND_SIZE, } /// /// The operator to be used for the comparison. The VerifyVersionInfo function uses this operator to compare a specified attribute /// value to the corresponding value for the currently running system. /// public enum VERSION_CONDITION : byte { /// The current value must be equal to the specified value. VER_EQUAL = 1, /// The current value must be greater than the specified value. VER_GREATER, /// The current value must be greater than or equal to the specified value. VER_GREATER_EQUAL, /// The current value must be less than the specified value. VER_LESS, /// The current value must be less than or equal to the specified value. VER_LESS_EQUAL, /// All product suites specified in the wSuiteMask member must be present in the current system. VER_AND, /// At least one of the specified product suites must be present in the current system. VER_OR, } /// /// A mask that indicates the member of the OSVERSIONINFOEX structure whose comparison operator is being set. This value corresponds /// to one of the bits specified in the dwTypeMask parameter for the VerifyVersionInfo function. /// [Flags] public enum VERSION_MASK : uint { /// dwMinorVersion VER_MINORVERSION = 0x0000001, /// dwMajorVersion VER_MAJORVERSION = 0x0000002, /// dwBuildNumber VER_BUILDNUMBER = 0x0000004, /// dwPlatformId VER_PLATFORMID = 0x0000008, /// wServicePackMinor VER_SERVICEPACKMINOR = 0x0000010, /// wServicePackMajor VER_SERVICEPACKMAJOR = 0x0000020, /// wSuiteMask VER_SUITENAME = 0x0000040, /// wProductType VER_PRODUCT_TYPE = 0x0000080, } /// The RtlCopyMemory routine copies the contents of a source memory block to a destination memory block. /// Datatype: void*. A pointer to the destination memory block to copy the bytes to. /// Datatype: const void*. A pointer to the source memory block to copy the bytes from. /// Datatype: size_t. The number of bytes to copy from the source to the destination. /// None /// /// /// RtlCopyMemory runs faster than RtlMoveMemory. However, RtlCopyMemory requires that the source memory block, /// which is defined by Source and Length, cannot overlap the destination memory block, which is defined by Destination and Length. /// In contrast, RtlMoveMemory correctly handles the case in which the source and destination memory blocks overlap. /// /// New drivers should use the RtlCopyMemory routine instead of RtlCopyBytes. /// /// Callers of RtlCopyMemory can be running at any IRQL if the source and destination memory blocks are in nonpaged system /// memory. Otherwise, the caller must be running at IRQL <= APC_LEVEL. /// /// // https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-rtlcopymemory // void RtlCopyMemory( Destination, Source, Length ); [DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)] [PInvokeData("wdm.h", MSDNShortId = "d204eeb4-e109-4a86-986f-0fccdda3f8f8")] public static extern void RtlCopyMemory(IntPtr Destination, IntPtr Source, SizeT Length); /// The RtlFillMemory routine fills a block of memory with the specified fill value. /// Datatype: void*. A pointer to the block of memory to be filled. /// Datatype: size_t. The number of bytes in the block of memory to be filled. /// /// Datatype: int. The value to fill the destination memory block with. This value is copied to every byte in the memory block that /// is defined by Destination and Length. /// /// None /// /// Callers of RtlFillMemory can be running at any IRQL if the destination memory block is in nonpaged system memory. /// Otherwise, the caller must be running at IRQL <= APC_LEVEL. /// // https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-rtlfillmemory // void RtlFillMemory( Destination, Length, Fill ); [DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)] [PInvokeData("wdm.h", MSDNShortId = "9a73331a-cc73-4a47-948b-a821600ca6a6")] public static extern void RtlFillMemory(IntPtr Destination, SizeT Length, int Fill); /// /// Copies the contents of a source memory block to a destination memory block, and supports overlapping source and destination /// memory blocks. /// /// A pointer to the destination memory block to copy the bytes to. /// A pointer to the source memory block to copy the bytes from. /// The number of bytes to copy from the source to the destination. /// None /// /// /// The source memory block, which is defined by Source and Length, can overlap the destination memory block, which is defined by /// Destination and Length. /// /// /// The RtlCopyMemory routine runs faster than RtlMoveMemory, but RtlCopyMemory requires that the source and /// destination memory blocks do not overlap. /// /// /// Callers of RtlMoveMemory can be running at any IRQL if the source and destination memory blocks are in non-paged system /// memory. Otherwise, the caller must be running at IRQL <= APC_LEVEL. /// /// // https://docs.microsoft.com/en-us/windows/win32/devnotes/rtlmovememory VOID RtlMoveMemory( _Out_ VOID UNALIGNED *Destination, _In_ // const VOID UNALIGNED *Source, _In_ SIZE_T Length ); [DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)] [PInvokeData("winnt.h", MSDNShortId = "D374F14D-24C7-4771-AD40-3AC37E7A2D2F")] public static extern void RtlMoveMemory([In] IntPtr Destination, [In] IntPtr Source, [In] SizeT Length); /// /// The RtlZeroMemory routine fills a block of memory with zeros, given a pointer to the block and the length, in bytes, to be filled. /// /// A pointer to the memory block to be filled with zeros. /// The number of bytes to fill with zeros. // https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/wdm/nf-wdm-rtlzeromemory [DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)] [PInvokeData("winnt.h")] public static extern void RtlZeroMemory(IntPtr Destination, SizeT Length); /// /// Contains processor-specific register data. The system uses CONTEXT structures to perform various internal operations. Refer to /// the header file WinNT.h for definitions of this structure for each processor architecture. /// // https://msdn.microsoft.com/en-us/library/windows/desktop/ms679284(v=vs.85).aspx [StructLayout(LayoutKind.Sequential)] public struct CONTEXT { /// public uint ContextFlags; /// public uint Dr0; /// public uint Dr1; /// public uint Dr2; /// public uint Dr3; /// public uint Dr6; /// public uint Dr7; // Retrieved by CONTEXT_FLOATING_POINT /// public FLOATING_SAVE_AREA FloatSave; // Retrieved by CONTEXT_SEGMENTS /// public uint SegGs; /// public uint SegFs; /// public uint SegEs; /// public uint SegDs; // Retrieved by CONTEXT_INTEGER /// public uint Edi; /// public uint Esi; /// public uint Ebx; /// public uint Edx; /// public uint Ecx; /// public uint Eax; // Retrieved by CONTEXT_CONTROL /// public uint Ebp; /// public uint Eip; /// public uint SegCs; /// public uint EFlags; /// public uint Esp; /// public uint SegSs; // Retrieved by CONTEXT_EXTENDED_REGISTERS /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)] public byte[] ExtendedRegisters; /// Represents the 80387 save area on WOW64. Refer to the header file WinNT.h for the definition of this structure. // https://msdn.microsoft.com/en-us/library/windows/desktop/ms681671(v=vs.85).aspx [PInvokeData("WinNT.h", MSDNShortId = "ms681671")] [StructLayout(LayoutKind.Sequential)] public struct FLOATING_SAVE_AREA { /// public int ControlWord; /// public int StatusWord; /// public int TagWord; /// public int ErrorOffset; /// public int ErrorSelector; /// public int DataOffset; /// public int DataSelector; /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 80)] public byte[] RegisterArea; /// public int Cr0NpxState; } /// Initializes a new instance of the struct. /// The context flags. public CONTEXT(uint flags) : this() { ContextFlags = flags; } } /// [StructLayout(LayoutKind.Sequential, Pack = 16)] public struct CONTEXT64 { /// public ulong P1Home; /// public ulong P2Home; /// public ulong P3Home; /// public ulong P4Home; /// public ulong P5Home; /// public ulong P6Home; /// public uint ContextFlags; /// public uint MxCsr; /// public ushort SegCs; /// public ushort SegDs; /// public ushort SegEs; /// public ushort SegFs; /// public ushort SegGs; /// public ushort SegSs; /// public uint EFlags; /// public ulong Dr0; /// public ulong Dr1; /// public ulong Dr2; /// public ulong Dr3; /// public ulong Dr6; /// public ulong Dr7; /// public ulong Rax; /// public ulong Rcx; /// public ulong Rdx; /// public ulong Rbx; /// public ulong Rsp; /// public ulong Rbp; /// public ulong Rsi; /// public ulong Rdi; /// public ulong R8; /// public ulong R9; /// public ulong R10; /// public ulong R11; /// public ulong R12; /// public ulong R13; /// public ulong R14; /// public ulong R15; /// public ulong Rip; /// public XSAVE_FORMAT64 DUMMYUNIONNAME; /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 26)] public M128A[] VectorRegister; /// public ulong VectorControl; /// public ulong DebugControl; /// public ulong LastBranchToRip; /// public ulong LastBranchFromRip; /// public ulong LastExceptionToRip; /// public ulong LastExceptionFromRip; /// [StructLayout(LayoutKind.Sequential)] public struct M128A { /// public ulong High; /// public long Low; } /// [StructLayout(LayoutKind.Sequential, Pack = 16)] public struct XSAVE_FORMAT64 { /// public ushort ControlWord; /// public ushort StatusWord; /// public byte TagWord; /// public byte Reserved1; /// public ushort ErrorOpcode; /// public uint ErrorOffset; /// public ushort ErrorSelector; /// public ushort Reserved2; /// public uint DataOffset; /// public ushort DataSelector; /// public ushort Reserved3; /// public uint MxCsr; /// public uint MxCsr_Mask; /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public M128A[] FloatRegisters; /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public M128A[] XmmRegisters; /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 96)] public byte[] Reserved4; } } /// Contains the hardware counter value. // typedef struct _HARDWARE_COUNTER_DATA { HARDWARE_COUNTER_TYPE Type; DWORD Reserved; DWORD64 Value;} HARDWARE_COUNTER_DATA, // *PHARDWARE_COUNTER_DATA; https://msdn.microsoft.com/en-us/library/windows/desktop/dd796394(v=vs.85).aspx [PInvokeData("Winnt.h", MSDNShortId = "dd796394")] [StructLayout(LayoutKind.Sequential)] public struct HARDWARE_COUNTER_DATA { /// The type of hardware counter data collected. For possible values, see the HARDWARE_COUNTER_TYPE enumeration. public HARDWARE_COUNTER_TYPE Type; /// Reserved. Initialize to zero. public uint Reserved; /// /// The counter index. Each hardware counter in a processor's performance monitoring unit (PMU) is identified by an index. /// public ulong Value; } /// Represents an entry in the function table on 64-bit Windows. // https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-runtime_function typedef struct _IMAGE_RUNTIME_FUNCTION_ENTRY { // DWORD BeginAddress; DWORD EndAddress; union { DWORD UnwindInfoAddress; DWORD UnwindData; } DUMMYUNIONNAME; } RUNTIME_FUNCTION, // *PRUNTIME_FUNCTION, _IMAGE_RUNTIME_FUNCTION_ENTRY, *_PIMAGE_RUNTIME_FUNCTION_ENTRY; [PInvokeData("winnt.h", MSDNShortId = "9ed16f9a-3403-4ba9-9968-f51f6788a1f8")] [StructLayout(LayoutKind.Sequential)] public struct IMAGE_RUNTIME_FUNCTION_ENTRY { /// The address of the start of the function. public uint BeginAddress; /// The address of the end of the function. public uint EndAddress; /// The address of the unwind information for the function. public uint UnwindInfoAddress; } /// Contains the thread profiling and hardware counter data that you requested. // typedef struct _PERFORMANCE_DATA { WORD Size; BYTE Version; BYTE HwCountersCount; DWORD ContextSwitchCount; DWORD64 // WaitReasonBitMap; DWORD64 CycleTime; DWORD RetryCount; DWORD Reserved; HARDWARE_COUNTER_DATA HwCounters[MAX_HW_COUNTERS];} // PERFORMANCE_DATA, *PPERFORMANCE_DATA; https://msdn.microsoft.com/en-us/library/windows/desktop/dd796401(v=vs.85).aspx [PInvokeData("Winnt.h", MSDNShortId = "dd796401")] [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct PERFORMANCE_DATA { private const int MAX_HW_COUNTERS = 16; /// The size of this structure. public ushort Size; /// The version of this structure. Must be set to PERFORMANCE_DATA_VERSION. public byte Version; /// /// The number of array elements in the HwCounters array that contain hardware counter data. A value of 3 means that the /// array contains data for three hardware counters, not that elements 0 through 2 contain counter data. /// public byte HwCountersCount; /// The number of context switches that occurred from the time profiling was enabled. public uint ContextSwitchCount; /// /// A bitmask that identifies the reasons for the context switches that occurred since the last time the data was read. For /// possible values, see the KWAIT_REASON enumeration (the enumeration is included in the Wdm.h file in the WDK). /// public ulong WaitReasonBitMap; /// The cycle time of the thread (excludes the time spent interrupted) from the time profiling was enabled. public ulong CycleTime; /// The number of times that the read operation read the data to ensure a consistent snapshot of the data. public uint RetryCount; /// Reserved. Set to zero. public uint Reserved; /// /// An array of HARDWARE_COUNTER_DATA structures that contain the counter values. The elements of the array that contain /// counter data relate directly to the bits set in the HardwareCounters bitmask that you specified when you called the /// EnableThreadProfiling function. For example, if you set bit 3 in the HardwareCounters bitmask, HwCounters[3] will /// contain the counter data for that counter. /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_HW_COUNTERS)] public HARDWARE_COUNTER_DATA[] HwCounters; /// Gets a default instance with the size pre-set. public static readonly PERFORMANCE_DATA Default = new PERFORMANCE_DATA { Size = (ushort)Marshal.SizeOf(typeof(PERFORMANCE_DATA)), Version = PERFORMANCE_DATA_VERSION }; } /// The SECURITY_CAPABILITIES structure defines the security capabilities of the app container. // https://docs.microsoft.com/en-us/windows/desktop/api/winnt/ns-winnt-_security_capabilities typedef struct _SECURITY_CAPABILITIES { // #if ... PISID AppContainerSid; #if ... PSID_AND_ATTRIBUTES Capabilities; #else PSID AppContainerSid; #endif #else // PSID_AND_ATTRIBUTES Capabilities; #endif DWORD CapabilityCount; DWORD Reserved; } SECURITY_CAPABILITIES, *PSECURITY_CAPABILITIES, *LPSECURITY_CAPABILITIES; [PInvokeData("winnt.h", MSDNShortId = "1A865519-E042-4871-886C-9AA64D71CCE4")] [StructLayout(LayoutKind.Sequential)] public struct SECURITY_CAPABILITIES { /// The SID of the app container. public PSID AppContainerSid; /// The specific capabilities. public IntPtr Capabilities; /// The number of the capabilities. public uint CapabilityCount; /// This member is reserved. Do not use it. public uint Reserved; } /// /// Specifies attributes for a user-mode scheduling (UMS) worker thread. /// This structure is used with the UpdateProcThreadAttribute function. /// // https://docs.microsoft.com/en-us/windows/desktop/api/winnt/ns-winnt-ums_create_thread_attributes typedef struct // _UMS_CREATE_THREAD_ATTRIBUTES { DWORD UmsVersion; PVOID UmsContext; PVOID UmsCompletionList; } UMS_CREATE_THREAD_ATTRIBUTES, *PUMS_CREATE_THREAD_ATTRIBUTES; [PInvokeData("winnt.h", MSDNShortId = "5d3e1721-c439-49bb-9cb6-8386fa8aaf50")] [StructLayout(LayoutKind.Sequential)] public struct UMS_CREATE_THREAD_ATTRIBUTES { /// The UMS version for which the application was built. This parameter must be UMS_VERSION. public uint UmsVersion; /// /// A pointer to a UMS thread context for the worker thread to be created. This pointer is provided by the CreateUmsThreadContext function. /// public PUMS_CONTEXT UmsContext; /// /// A pointer to a UMS completion list. This pointer is provided by the CreateUmsCompletionList function. The newly created /// worker thread is queued to the specified completion list. /// public PUMS_COMPLETION_LIST UmsCompletionList; /// Initializes a new instance of the struct. /// /// A UMS thread context for the worker thread to be created. This pointer is provided by the CreateUmsThreadContext function. /// /// /// A UMS completion list. This pointer is provided by the CreateUmsCompletionList function. The newly created worker thread is /// queued to the specified completion list. /// public UMS_CREATE_THREAD_ATTRIBUTES(PUMS_CONTEXT ctx, PUMS_COMPLETION_LIST completionList) { UmsVersion = UMS_VERSION; UmsContext = ctx; UmsCompletionList = completionList; } } /// [PInvokeData("winnt.h")] [StructLayout(LayoutKind.Sequential)] public struct UNWIND_HISTORY_TABLE { /// public uint Count; /// public byte LocalHint; /// public byte GlobalHint; /// public byte Search; /// public byte Once; /// public ulong LowAddress; /// public ulong HighAddress; /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] public UNWIND_HISTORY_TABLE_ENTRY[] Entry; } /// [PInvokeData("winnt.h")] [StructLayout(LayoutKind.Sequential)] public struct UNWIND_HISTORY_TABLE_ENTRY { /// public ulong ImageBase; /// public IMAGE_RUNTIME_FUNCTION_ENTRY FunctionEntry; } /// /// Represents a context frame on WOW64. Refer to the header file WinNT.h for the definition of this structure. /// /// /// /// In the following versions of Windows, Slot 1 of Thread Local Storage (TLS) holds a pointer to a structure that contains a /// WOW64_CONTEXT structure starting at offset 4. This might change in later versions of Windows. /// /// /// /// Windows Vista /// Windows Server 2008 /// /// /// Windows 7 /// Windows Server 2008 R2 /// /// /// Windows 8 /// Windows Server 2012 /// /// /// Windows 8.1 /// Windows Server 2012 R2 /// /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/winnt/ns-winnt-_wow64_context [PInvokeData("winnt.h", MSDNShortId = "b27205a2-2c33-4f45-8948-9919bcd2355a")] [StructLayout(LayoutKind.Sequential)] public struct WOW64_CONTEXT { /// public WOW64_CONTEXT_FLAGS ContextFlags; /// public uint Dr0; /// public uint Dr1; /// public uint Dr2; /// public uint Dr3; /// public uint Dr6; /// public uint Dr7; /// public WOW64_FLOATING_SAVE_AREA FloatSave; /// public uint SegGs; /// public uint SegFs; /// public uint SegEs; /// public uint SegDs; /// public uint Edi; /// public uint Esi; /// public uint Ebx; /// public uint Edx; /// public uint Ecx; /// public uint Eax; /// public uint Ebp; /// public uint Eip; /// public uint SegCs; /// public uint EFlags; /// public uint Esp; /// public uint SegSs; /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)] public byte[] ExtendedRegisters; } /// /// Represents the 80387 save area on WOW64. Refer to the header file WinNT.h for the definition of this structure. /// // https://docs.microsoft.com/en-us/windows/desktop/api/winnt/ns-winnt-_wow64_floating_save_area [PInvokeData("winnt.h", MSDNShortId = "56fba1c1-432b-40a8-b882-e4c637c03d5d")] [StructLayout(LayoutKind.Sequential)] public struct WOW64_FLOATING_SAVE_AREA { /// public uint ControlWord; /// public uint StatusWord; /// public uint TagWord; /// public uint ErrorOffset; /// public uint ErrorSelector; /// public uint DataOffset; /// public uint DataSelector; /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 80)] public byte[] RegisterArea; /// public uint Cr0NpxState; } /// /// /// Describes an entry in the descriptor table for a 32-bit thread on a 64-bit system. This structure is valid only on 64-bit systems. /// /// /// /// /// The Wow64GetThreadSelectorEntry function fills this structure with information from an entry in the descriptor table. You can use /// this information to convert a segment-relative address to a linear virtual address. /// /// /// The base address of a segment is the address of offset 0 in the segment. To calculate this value, combine the BaseLow, /// BaseMid, and BaseHi members. /// /// /// The limit of a segment is the address of the last byte that can be addressed in the segment. To calculate this value, combine the /// LimitLow and LimitHi members. /// /// /// The WOW64_LDT_ENTRY structure has the same layout for a 64-bit process as the LDT_ENTRY structure has for a 32-bit process. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/winnt/ns-winnt-_wow64_ldt_entry typedef struct _WOW64_LDT_ENTRY { WORD // LimitLow; WORD BaseLow; union { struct { BYTE BaseMid; BYTE Flags1; BYTE Flags2; BYTE BaseHi; } Bytes; struct { DWORD BaseMid : 8; // DWORD Type : 5; DWORD Dpl : 2; DWORD Pres : 1; DWORD LimitHi : 4; DWORD Sys : 1; DWORD Reserved_0 : 1; DWORD Default_Big : 1; // DWORD Granularity : 1; DWORD BaseHi : 8; } Bits; } HighWord; } WOW64_LDT_ENTRY, *PWOW64_LDT_ENTRY; [PInvokeData("winnt.h", MSDNShortId = "a571cd2f-0873-4ad5-bcb8-c0da2d47a820")] [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct WOW64_LDT_ENTRY { /// /// The low-order part of the address of the last byte in the segment. /// public ushort LimitLow; /// /// The low-order part of the base address of the segment. /// public ushort BaseLow; /// /// Middle bits (16-23) of the base address of the segment. /// public byte BaseMid; private ushort Flags; /// /// The high bits (24-31) of the base address of the segment. /// public byte BaseHi; /// /// The type of segment. This member can be one of the following values: /// public byte Type { get => GetBits((byte)Flags, 0, 5); set => SetBits(ref Flags, 0, 5, value); } /// /// /// The privilege level of the descriptor. This member is an integer value in the range 0 (most privileged) through 3 (least privileged). /// /// public byte Dpl { get => GetBits((byte)Flags, 5, 2); set => SetBits(ref Flags, 5, 2, value); } /// /// The present flag. This member is 1 if the segment is present in physical memory or 0 if it is not. /// public bool Pres { get => GetBit(Flags, 7); set => SetBit(ref Flags, 7, value); } /// /// The high bits (16–19) of the address of the last byte in the segment. /// public byte LimitHi { get => GetBits((byte)Flags, 8, 4); set => SetBits(ref Flags, 8, 4, value); } /// /// /// The space that is available to system programmers. This member might be used for marking segments in some system-specific way. /// /// public bool Sys { get => GetBit(Flags, 12); set => SetBit(ref Flags, 12, value); } /// /// Reserved. /// public bool Reserved_0 { get => GetBit(Flags, 13); set => SetBit(ref Flags, 13, value); } /// /// /// The size of segment. If the segment is a data segment, this member contains 1 if the segment is larger than 64 kilobytes (KB) /// or 0 if the segment is smaller than or equal to 64 KB. /// /// /// If the segment is a code segment, this member contains 1. The segment runs with the default (native mode) instruction set. /// /// public bool Default_Big { get => GetBit(Flags, 14); set => SetBit(ref Flags, 14, value); } /// /// The granularity. This member contains 0 if the segment is byte granular, 1 if the segment is page granular. /// public bool Granularity { get => GetBit(Flags, 15); set => SetBit(ref Flags, 15, value); } } /// Used by thread context functions. [PInvokeData("winnt.h")] public static class CONTEXT_FLAG { /// Undocumented. public const uint CONTEXT_AMD64 = 0x00100000; /// Undocumented. public const uint CONTEXT_ARM = 0x00200000; /// Undocumented. public const uint CONTEXT_EXCEPTION_ACTIVE = 0x08000000; /// Undocumented. public const uint CONTEXT_EXCEPTION_REPORTING = 0x80000000; /// Undocumented. public const uint CONTEXT_EXCEPTION_REQUEST = 0x40000000; /// Undocumented. public const uint CONTEXT_i386 = 0x00010000; /// Undocumented. public const uint CONTEXT_KERNEL_DEBUGGER = 0x04000000; /// Undocumented. public const uint CONTEXT_SERVICE_ACTIVE = 0x10000000; private static readonly uint systemContext; static CONTEXT_FLAG() { GetNativeSystemInfo(out var info); switch (info.wProcessorArchitecture) { case ProcessorArchitecture.PROCESSOR_ARCHITECTURE_INTEL: systemContext = CONTEXT_i386; break; case ProcessorArchitecture.PROCESSOR_ARCHITECTURE_ARM: systemContext = CONTEXT_ARM; break; case ProcessorArchitecture.PROCESSOR_ARCHITECTURE_AMD64: systemContext = CONTEXT_AMD64; break; default: throw new InvalidOperationException("Processor context not recognized."); } } /// Undocumented. public static uint CONTEXT_ALL => CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS | CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS; /// Undocumented. public static uint CONTEXT_CONTROL => systemContext | 0x00000001; /// Undocumented. public static uint CONTEXT_DEBUG_REGISTERS => systemContext | 0x00000010; /// Undocumented. public static uint CONTEXT_EXTENDED_REGISTERS => systemContext | 0x00000020; /// Undocumented. public static uint CONTEXT_FLOATING_POINT => systemContext | 0x00000008; /// Undocumented. public static uint CONTEXT_FULL => CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT; /// Undocumented. public static uint CONTEXT_INTEGER => systemContext | 0x00000002; /// Undocumented. public static uint CONTEXT_SEGMENTS => systemContext | 0x00000004; /// Undocumented. public static uint CONTEXT_XSTATE => systemContext | 0x00000040; } /// /// Contains processor-specific register data. The system uses CONTEXT structures to perform various internal operations. /// Refer to the header file WinNT.h for definitions of this structure for each processor architecture. /// // https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-_arm64_nt_context typedef struct _ARM64_NT_CONTEXT { DWORD // ContextFlags; DWORD Cpsr; union { struct { DWORD64 X0; DWORD64 X1; DWORD64 X2; DWORD64 X3; DWORD64 X4; DWORD64 X5; DWORD64 X6; // DWORD64 X7; DWORD64 X8; DWORD64 X9; DWORD64 X10; DWORD64 X11; DWORD64 X12; DWORD64 X13; DWORD64 X14; DWORD64 X15; DWORD64 X16; // DWORD64 X17; DWORD64 X18; DWORD64 X19; DWORD64 X20; DWORD64 X21; DWORD64 X22; DWORD64 X23; DWORD64 X24; DWORD64 X25; DWORD64 X26; // DWORD64 X27; DWORD64 X28; DWORD64 Fp; DWORD64 Lr; } DUMMYSTRUCTNAME; DWORD64 X[31]; } DUMMYUNIONNAME; DWORD64 Sp; DWORD64 Pc; // ARM64_NT_NEON128 V[32]; DWORD Fpcr; DWORD Fpsr; DWORD Bcr[ARM64_MAX_BREAKPOINTS]; DWORD64 Bvr[ARM64_MAX_BREAKPOINTS]; DWORD // Wcr[ARM64_MAX_WATCHPOINTS]; DWORD64 Wvr[ARM64_MAX_WATCHPOINTS]; } ARM64_NT_CONTEXT, *PARM64_NT_CONTEXT; [PInvokeData("winnt.h", MSDNShortId = "a6c201b3-4402-4de4-89c7-e6e2fbcd27f7")] public class SafeCONTEXT : SafeHandle { private SafeHGlobalHandle buffer; /// Initializes a new instance of the class. /// The context flags. public SafeCONTEXT(uint contextFlags) : base(IntPtr.Zero, true) { uint len = 0; InitializeContext(IntPtr.Zero, contextFlags, out _, ref len); buffer = new SafeHGlobalHandle((int)len); if (!InitializeContext(buffer.DangerousGetHandle(), contextFlags, out var ptr, ref len)) Win32Error.ThrowLastError(); SetHandle(ptr); } /// public override bool IsInvalid => handle == IntPtr.Zero; /// Creates a new instance by copying from a CONTEXT structure. /// The type of the context to copy from. /// The context value. /// The context flags. /// A new instance. public static SafeCONTEXT FromContextStruct(in TContext context, uint contextFlags) where TContext : struct { var output = new SafeCONTEXT(contextFlags); var pCtx = new PinnedObject(context); if (!CopyContext(output, contextFlags, pCtx)) Win32Error.ThrowLastError(); return output; } /// Clones this instance. /// The context flags. /// A full copy of this instance. public SafeCONTEXT Clone(uint contextFlags) { var output = new SafeCONTEXT(contextFlags); if (!CopyContext(output, contextFlags, handle)) Win32Error.ThrowLastError(); return output; } /// Converts to a CONTEXT structure. /// The type of the context structure to which to convert. /// The context structure. public TContext ToContextStruct() where TContext : struct => handle.ToStructure(buffer.Size - handle.ToInt32() + buffer.DangerousGetHandle().ToInt32()); /// protected override bool ReleaseHandle() { buffer.Dispose(); SetHandle(IntPtr.Zero); return true; } } } }