Vanara/PInvoke/NtDll/NtDll.cs

2348 lines
109 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using Vanara.Extensions;
using Vanara.Extensions.Reflection;
using Vanara.InteropServices;
namespace Vanara.PInvoke
{
/// <summary>Platform invokable enumerated types, constants and functions from ntdll.h</summary>
public static partial class NtDll
{
/// <summary>
/// <para>[This function may be changed or removed from Windows without further notice.]</para>
/// <para>
/// A notification callback function specified with the <c>LdrRegisterDllNotification</c> function. The loader calls this function
/// when a DLL is first loaded.
/// </para>
/// <para><c>Warning:</c> It is unsafe for the notification callback function to call functions in any DLL.</para>
/// </summary>
/// <returns>
/// <para>This callback function does not return a value.</para>
/// </returns>
/// <remarks>
/// <para>The notification callback function is called before dynamic linking takes place.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/DevNotes/ldrdllnotification VOID CALLBACK LdrDllNotification( _In_ ULONG
// NotificationReason, _In_ PCLDR_DLL_NOTIFICATION_DATA NotificationData, _In_opt_ PVOID Context );
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
[PInvokeData("ntldr.h", MSDNShortId = "12202797-c80c-4fa3-9cc4-dcb1a9f01551")]
public delegate void LdrDllNotification(uint NotificationReason, ref LDR_DLL_NOTIFICATION_DATA NotificationData, [In, Optional] IntPtr Context);
/// <summary>Lists the different types of notifications that can be received by an enlistment.</summary>
[PInvokeData("ktmtypes.h", MSDNShortId = "32c2be6a-c75a-9391-274d-a53a6e2b74c8")]
public enum NOTIFICATION_MASK
{
/// <summary>A mask that indicates all valid bits for a transaction notification.</summary>
TRANSACTION_NOTIFY_MASK = 0x3FFFFFFF,
/// <summary>
/// This notification is called after a client calls CommitTransaction and either no resource manager (RM) supports single-phase
/// commit or a superior transaction manager (TM) calls PrePrepareEnlistment. This notification is received by the RMs
/// indicating that they should complete any work that could cause other RMs to need to enlist in a transaction, such as
/// flushing its cache. After completing these operations the RM must call PrePrepareComplete. To receive this notification the
/// RM must also support TRANSACTION_NOTIFY_PREPARE and TRANSACTION_NOTIFY_COMMIT.
/// </summary>
TRANSACTION_NOTIFY_PREPREPARE = 0x00000001,
/// <summary>
/// This notification is called after the TRANSACTION_NOTIFY_PREPREPARE processing is complete. It signals the RM to complete
/// all the work that is associated with this enlistment so that it can guarantee that a commit operation could succeed and an
/// abort operation could also succeed. Typically, the bulk of the work for a transaction is done during the prepare phase. For
/// durable RMs, they must log their state prior to calling the PrepareComplete function. This is the last chance for the RM to
/// request that the transaction be rolled back.
/// </summary>
TRANSACTION_NOTIFY_PREPARE = 0x00000002,
/// <summary>
/// This notification signals the RM to complete all the work that is associated with this enlistment. Typically, the RM
/// releases any locks, releases any information necessary to roll back the transaction. The RM must respond by calling the
/// CommitComplete function when it has finished these operations.
/// </summary>
TRANSACTION_NOTIFY_COMMIT = 0x00000004,
/// <summary>This notification signals the RM to undo all the work it has done that is associated with the transaction.</summary>
TRANSACTION_NOTIFY_ROLLBACK = 0x00000008,
/// <summary>This notification signals to the superior TM that a pre-prepare operation was completed successfully.</summary>
TRANSACTION_NOTIFY_PREPREPARE_COMPLETE = 0x00000010,
/// <summary>This notification signals to the superior TM that a prepare operation was completed successfully.</summary>
TRANSACTION_NOTIFY_PREPARE_COMPLETE = 0x00000020,
/// <summary>This notification signals to the superior TM that a commit operation was completed successfully.</summary>
TRANSACTION_NOTIFY_COMMIT_COMPLETE = 0x00000040,
/// <summary>This notification signals to the superior TM that a rollback operation was completed successfully.</summary>
TRANSACTION_NOTIFY_ROLLBACK_COMPLETE = 0x00000080,
/// <summary>
/// This notification signals to RMs that they should recover their state because a transaction outcome must be redelivered. For
/// example, when an RM is recovered, and when there are transactions left in-doubt. This notification is delivered once the
/// in-doubt state is resolved.
/// </summary>
TRANSACTION_NOTIFY_RECOVER = 0x00000100,
/// <summary>
/// This notification signals the RM to complete and commit the transaction without using a two-phase commit protocol. If the RM
/// wants to use a two-phase operation, it must respond by calling the SinglePhaseReject function.
/// </summary>
TRANSACTION_NOTIFY_SINGLE_PHASE_COMMIT = 0x00000200,
/// <summary>KTM is signaling to the superior TM to perform a commit operation.</summary>
TRANSACTION_NOTIFY_DELEGATE_COMMIT = 0x00000400,
/// <summary>KTM is signaling to the superior TM to query the status of an in-doubt transaction.</summary>
TRANSACTION_NOTIFY_RECOVER_QUERY = 0x00000800,
/// <summary>
/// This notification signals to the superior TM that pre-prepare notifications must be delivered on the specified enlistment.
/// </summary>
TRANSACTION_NOTIFY_ENLIST_PREPREPARE = 0x00001000,
/// <summary>This notification indicates that the recovery operation is complete for this RM.</summary>
TRANSACTION_NOTIFY_LAST_RECOVER = 0x00002000,
/// <summary>
/// The specified transaction is in an in-doubt state. The RM receives this notification during recovery operations when a
/// transaction has been prepared, but there is no superior transaction manager (TM) available. For example, when a transaction
/// involves a remote TM and that node is unavailable, its node is unavailable, or the local Distributed Transaction Coordinator
/// service is unavailable, the transaction state is in-doubt.
/// </summary>
TRANSACTION_NOTIFY_INDOUBT = 0x00004000,
/// <summary>Undocumented or not supported.</summary>
TRANSACTION_NOTIFY_PROPAGATE_PULL = 0x00008000,
/// <summary>Undocumented or not supported.</summary>
TRANSACTION_NOTIFY_PROPAGATE_PUSH = 0x00010000,
/// <summary>Undocumented or not supported.</summary>
TRANSACTION_NOTIFY_MARSHAL = 0x00020000,
/// <summary>Undocumented or not supported.</summary>
TRANSACTION_NOTIFY_ENLIST_MASK = 0x00040000,
/// <summary>Undocumented or not supported.</summary>
TRANSACTION_NOTIFY_RM_DISCONNECTED = 0x01000000,
/// <summary>Undocumented or not supported.</summary>
TRANSACTION_NOTIFY_TM_ONLINE = 0x02000000,
/// <summary>Undocumented or not supported.</summary>
TRANSACTION_NOTIFY_COMMIT_REQUEST = 0x04000000,
/// <summary>Undocumented or not supported.</summary>
TRANSACTION_NOTIFY_PROMOTE = 0x08000000,
/// <summary>Undocumented or not supported.</summary>
TRANSACTION_NOTIFY_PROMOTE_NEW = 0x10000000,
/// <summary>
/// Signals to RMs that there is outcome information available, and that a request for that information should be made.
/// </summary>
TRANSACTION_NOTIFY_REQUEST_OUTCOME = 0x20000000,
/// <summary>Reserved.</summary>
TRANSACTION_NOTIFY_COMMIT_FINALIZE = 0x40000000,
}
/// <summary>Indicates the kind of system information to be retrieved by <see cref="NtQuerySystemInformation"/>.</summary>
[PInvokeData("winternl.h", MSDNShortId = "553ec7b9-c5eb-4955-8dc0-f1c06f59fe31")]
public enum SYSTEM_INFORMATION_CLASS
{
/// <summary>
/// Returns the number of processors in the system in a SYSTEM_BASIC_INFORMATION structure. Use the GetSystemInfo function instead.
/// </summary>
[Obsolete("Use the GetSystemInfo function instead.")]
[CorrespondingType(typeof(SYSTEM_BASIC_INFORMATION))]
SystemBasicInformation = 0,
/// <summary>
/// Returns an opaque SYSTEM_PERFORMANCE_INFORMATION structure that can be used to generate an unpredictable seed for a random
/// number generator. Use the CryptGenRandomfunction instead.
/// </summary>
[Obsolete("Use the CryptGenRandomfunction function instead.")]
SystemPerformanceInformation = 2,
/// <summary>
/// Returns an opaque SYSTEM_TIMEOFDAY_INFORMATION structure that can be used to generate an unpredictable seed for a random
/// number generator. Use the CryptGenRandom function instead.
/// </summary>
[Obsolete("Use the CryptGenRandom function instead.")]
SystemTimeOfDayInformation = 3,
/// <summary>
/// Returns an array of SYSTEM_PROCESS_INFORMATION structures, one for each process running in the system.
/// <para>
/// These structures contain information about the resource usage of each process, including the number of threads and handles
/// used by the process, the peak page-file usage, and the number of memory pages that the process has allocated.
/// </para>
/// </summary>
[CorrespondingType(typeof(SYSTEM_PROCESS_INFORMATION[]))]
SystemProcessInformation = 5,
/// <summary>
/// Returns an array of SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION structures, one for each processor installed in the system.
/// </summary>
[CorrespondingType(typeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION[]))]
SystemProcessorPerformanceInformation = 8,
/// <summary>
/// Returns an opaque SYSTEM_INTERRUPT_INFORMATION structure that can be used to generate an unpredictable seed for a random
/// number generator. Use the CryptGenRandom function instead.
/// </summary>
[Obsolete("Use the CryptGenRandom function instead.")]
SystemInterruptInformation = 23,
/// <summary>
/// Returns an opaque SYSTEM_EXCEPTION_INFORMATION structure that can be used to generate an unpredictable seed for a random
/// number generator. Use the CryptGenRandom function instead.
/// </summary>
[Obsolete("Use the CryptGenRandom function instead.")]
SystemExceptionInformation = 33,
/// <summary>Returns a SYSTEM_REGISTRY_QUOTA_INFORMATION structure.</summary>
[CorrespondingType(typeof(SYSTEM_REGISTRY_QUOTA_INFORMATION))]
SystemRegistryQuotaInformation = 37,
/// <summary>
/// Returns an opaque SYSTEM_LOOKASIDE_INFORMATION structure that can be used to generate an unpredictable seed for a random
/// number generator. Use the CryptGenRandom function instead.
/// </summary>
[Obsolete("Use the CryptGenRandom function instead.")]
SystemLookasideInformation = 45,
/// <summary>
/// Returns policy information in a SYSTEM_POLICY_INFORMATION structure. Use the SLGetWindowsInformation function instead to
/// obtain policy information.
/// </summary>
[Obsolete("Use the SLGetWindowsInformation function instead.")]
SystemPolicyInformation = 134,
}
/// <summary>
/// <para>
/// The <c>DbgPrompt</c> routine displays a caller-specified user prompt string on the kernel debugger's display device and obtains
/// a user response string.
/// </para>
/// </summary>
/// <param name="Prompt">
/// <para>
/// A pointer to a NULL-terminated constant character string that the debugger will display as a user prompt. The maximum size of
/// this string is 512 characters.
/// </para>
/// </param>
/// <param name="Response">
/// <para>
/// A pointer to a character array buffer that receives the user's response, including a terminating newline character. The maximum
/// size of this buffer is 512 characters.
/// </para>
/// </param>
/// <param name="Length">
/// <para>TBD</para>
/// </param>
/// <returns>
/// <para>
/// <c>DbgPrompt</c> returns the number of characters that the Response buffer received, including the terminating newline
/// character. <c>DbgPrompt</c> returns zero if it receives no characters.
/// </para>
/// </returns>
/// <remarks>
/// <para>
/// The <c>DbgPrompt</c> routine displays the specified prompt string on the kernel debugger's display device and then reads a line
/// of user input text.
/// </para>
/// <para>
/// After <c>DbgPrompt</c> returns, the Response buffer contains the user's response, including the terminating newline character.
/// The user response string is not NULL-terminated.
/// </para>
/// <para>
/// The following code example asks if the user wants to continue and accepts the letter "y" for yes and the letter "n" for no.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/ntddk/nf-ntddk-dbgprompt NTSYSAPI ULONG DbgPrompt( PCCH
// Prompt, PCH Response, ULONG Length );
[DllImport(Lib.NtDll, SetLastError = false, ExactSpelling = true, CharSet = CharSet.Ansi)]
[PInvokeData("ntddk.h", MSDNShortId = "4bb44aab-7032-4cc7-89e3-6ac3bee233d3")]
public static extern uint DbgPrompt(string Prompt, StringBuilder Response, uint Length);
/// <summary>
/// <para>
/// [Some information relates to pre-released product which may be substantially modified before it's commercially released.
/// Microsoft makes no warranties, express or implied, with respect to the information provided here.]
/// </para>
/// <para>
/// This function forcefully terminates the calling program if it is invoked inside a loader callout. Otherwise, it has no effect.
/// </para>
/// </summary>
/// <returns>
/// <para>This function does not return a value.</para>
/// </returns>
/// <remarks>
/// <para>
/// This routine does not catch all potential deadlock cases; it is possible for a thread inside a loader callout to acquire a lock
/// while some thread outside a loader callout holds the same lock and makes a call into the loader. In other words, there can be a
/// lock order inversion between the loader lock and a client lock.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/DevNotes/ldrfastfailinloadercallout VOID NTAPI LdrFastFailInLoaderCallout(void);
[DllImport(Lib.NtDll, SetLastError = false, ExactSpelling = true)]
[PInvokeData("ntldr.h", MSDNShortId = "5C10BF04-B7C7-4481-A184-FDD418FE5F52")]
public static extern void LdrFastFailInLoaderCallout();
/// <summary>
/// <para>[This function may be changed or removed from Windows without further notice.]</para>
/// <para>Registers for notification when a DLL is first loaded. This notification occurs before dynamic linking takes place.</para>
/// </summary>
/// <param name="Flags">This parameter must be zero.</param>
/// <param name="NotificationFunction">
/// A pointer to an LdrDllNotification notification callback function to call when the DLL is loaded.
/// </param>
/// <param name="Context">A pointer to context data for the callback function.</param>
/// <param name="Cookie">
/// A pointer to a variable to receive an identifier for the callback function. This identifier is used to unregister the
/// notification callback function.
/// </param>
/// <returns>
/// <para>If the function succeeds, it returns <c>STATUS_SUCCESS</c>.</para>
/// <para>
/// The forms and significance of <c>NTSTATUS</c> error codes are listed in the Ntstatus.h header file available in the WDK, and are
/// described in the WDK documentation.
/// </para>
/// </returns>
/// <remarks>
/// This function has no associated header file. The associated import library, Ntdll.lib, is available in the WDK. You can also use
/// the <c>LoadLibrary</c> and <c>GetProcAddress</c> functions to dynamically link to Ntdll.dll.
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/devnotes/ldrregisterdllnotification NTSTATUS NTAPI LdrRegisterDllNotification(
// _In_ ULONG Flags, _In_ PLDR_DLL_NOTIFICATION_FUNCTION NotificationFunction, _In_opt_ PVOID Context, _Out_ PVOID *Cookie );
[DllImport(Lib.NtDll, SetLastError = false, ExactSpelling = true)]
[PInvokeData("", MSDNShortId = "c2757aa0-76fa-427a-a4f6-cb26e7f7d0d1")]
public static extern NTStatus LdrRegisterDllNotification([Optional] uint Flags, LdrDllNotification NotificationFunction, [Optional] IntPtr Context, out IntPtr Cookie);
/// <summary>
/// <para>[This function may be changed or removed from Windows without further notice.]</para>
/// <para>Cancels DLL load notification previously registered by calling the <c>LdrRegisterDllNotification</c> function.</para>
/// </summary>
/// <returns>
/// <para>Returns an <c>NTSTATUS</c> or error code.</para>
/// <para>If the function succeeds, it returns <c>STATUS_SUCCESS</c>.</para>
/// <para>If the callback function is not found, the function returns <c>STATUS_DLL_NOT_FOUND</c>.</para>
/// <para>
/// The forms and significance of <c>NTSTATUS</c> error codes are listed in the Ntstatus.h header file available in the WDK, and are
/// described in the WDK documentation.
/// </para>
/// </returns>
/// <remarks>
/// <para>
/// This function has no associated header file. The associated import library, Ntdll.lib, is available in the WDK. You can also use
/// the <c>LoadLibrary</c> and <c>GetProcAddress</c> functions to dynamically link to Ntdll.dll.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/DevNotes/ldrunregisterdllnotification NTSTATUS NTAPI
// LdrUnregisterDllNotification( _In_ PVOID Cookie );
[DllImport(Lib.NtDll, SetLastError = false, ExactSpelling = true)]
[PInvokeData("ntldr.h", MSDNShortId = "18c3a027-e3cb-4083-afdc-00f416a70d8c")]
public static extern NTStatus LdrUnregisterDllNotification([In] IntPtr Cookie);
/// <summary>
/// <para>Deprecated. Closes the specified handle. <c>NtClose</c> is superseded by CloseHandle.</para>
/// </summary>
/// <param name="Handle">
/// <para>The handle being closed.</para>
/// </param>
/// <returns>
/// <para>The various NTSTATUS values are defined in NTSTATUS.H, which is distributed with the Windows DDK.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>STATUS_SUCCESS</term>
/// <term>The handle was closed.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>The <c>NtClose</c> function closes handles to the following objects.</para>
/// <list type="bullet">
/// <item>
/// <term>Access token</term>
/// </item>
/// <item>
/// <term>Communications device</term>
/// </item>
/// <item>
/// <term>Console input</term>
/// </item>
/// <item>
/// <term>Console screen buffer</term>
/// </item>
/// <item>
/// <term>Event</term>
/// </item>
/// <item>
/// <term>File</term>
/// </item>
/// <item>
/// <term>File mapping</term>
/// </item>
/// <item>
/// <term>Job</term>
/// </item>
/// <item>
/// <term>Mailslot</term>
/// </item>
/// <item>
/// <term>Mutex</term>
/// </item>
/// <item>
/// <term>Named pipe</term>
/// </item>
/// <item>
/// <term>Process</term>
/// </item>
/// <item>
/// <term>Semaphore</term>
/// </item>
/// <item>
/// <term>Socket</term>
/// </item>
/// <item>
/// <term>Thread</term>
/// </item>
/// </list>
/// <para>Because there is no import library for this function, you must use GetProcAddress.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winternl/nf-winternl-ntclose __kernel_entry NTSTATUS NtClose( IN HANDLE
// Handle );
[DllImport(Lib.NtDll, SetLastError = false, ExactSpelling = true)]
[PInvokeData("winternl.h")]
[Obsolete]
public static extern NTStatus NtClose(IntPtr Handle);
/// <summary>
/// <para>
/// The <c>NtCompareTokens</c> function compares two access tokens and determines whether they are equivalent with respect to a call
/// to the <c>AccessCheck</c> function.
/// </para>
/// </summary>
/// <returns>
/// <para>If the function succeeds, the function returns STATUS_SUCCESS.</para>
/// <para>If the function fails, it returns an <c>NTSTATUS</c> error code.</para>
/// </returns>
/// <remarks>
/// <para>Two access control tokens are considered to be equivalent if all of the following conditions are true:</para>
/// <list type="bullet">
/// <item>
/// <term>Every security identifier (SID) that is present in either token is also present in the other token.</term>
/// </item>
/// <item>
/// <term>Neither or both of the tokens are restricted.</term>
/// </item>
/// <item>
/// <term>If both tokens are restricted, every SID that is restricted in one token is also restricted in the other token.</term>
/// </item>
/// <item>
/// <term>Every privilege present in either token is also present in the other token.</term>
/// </item>
/// </list>
/// <para>
/// This function has no associated import library or header file; you must call it using the <c>LoadLibrary</c> and
/// <c>GetProcAddress</c> functions.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/SecAuthZ/ntcomparetokens NTSTATUS NTAPI NtCompareTokens( _In_ HANDLE
// FirstTokenHandle, _In_ HANDLE SecondTokenHandle, _Out_ PBOOLEAN Equal );
[DllImport(Lib.NtDll, SetLastError = false, ExactSpelling = true)]
[PInvokeData("Ntseapi.h", MSDNShortId = "3a07ddc6-9748-4f96-a597-2af6b4282e56")]
public static extern NTStatus NtCompareTokens([In] IntPtr FirstTokenHandle, [In] IntPtr SecondTokenHandle, [MarshalAs(UnmanagedType.U1)] out bool Equal);
/// <summary>
/// <para>
/// [ <c>NtQuerySystemInformation</c> may be altered or unavailable in future versions of Windows. Applications should use the
/// alternate functions listed in this topic.]
/// </para>
/// <para>Retrieves the specified system information.</para>
/// </summary>
/// <param name="SystemInformationClass">
/// <para>
/// One of the values enumerated in SYSTEM_INFORMATION_CLASS, which indicate the kind of system information to be retrieved. These
/// include the following values.
/// </para>
/// <para>SystemBasicInformation</para>
/// <para>
/// Returns the number of processors in the system in a <c>SYSTEM_BASIC_INFORMATION</c> structure. Use the GetSystemInfo function instead.
/// </para>
/// <para>SystemCodeIntegrityInformation</para>
/// <para>
/// Returns a <c>SYSTEM_CODEINTEGRITY_INFORMATION</c> structure that can be used to determine the options being enforced by Code
/// Integrity on the system.
/// </para>
/// <para>SystemExceptionInformation</para>
/// <para>
/// Returns an opaque <c>SYSTEM_EXCEPTION_INFORMATION</c> structure that can be used to generate an unpredictable seed for a random
/// number generator. Use the CryptGenRandom function instead.
/// </para>
/// <para>SystemInterruptInformation</para>
/// <para>
/// Returns an opaque <c>SYSTEM_INTERRUPT_INFORMATION</c> structure that can be used to generate an unpredictable seed for a random
/// number generator. Use the CryptGenRandom function instead.
/// </para>
/// <para>SystemKernelVaShadowInformation</para>
/// <para>
/// Returns a <c>SYSTEM_KERNEL_VA_SHADOW_INFORMATION</c> structure that can be used to determine the speculation control settings
/// for attacks involving rogue data cache loads (such as CVE-2017-5754).
/// </para>
/// <para>SystemLeapSecondInformation</para>
/// <para>
/// Returns an opaque <c>SYSTEM_LEAP_SECOND_INFORMATION</c> structure that can be used to enable or disable leap seconds
/// system-wide. This setting will persist even after a reboot of the system.
/// </para>
/// <para>SystemLookasideInformation</para>
/// <para>
/// Returns an opaque <c>SYSTEM_LOOKASIDE_INFORMATION</c> structure that can be used to generate an unpredictable seed for a random
/// number generator. Use the CryptGenRandom function instead.
/// </para>
/// <para>SystemPerformanceInformation</para>
/// <para>
/// Returns an opaque <c>SYSTEM_PERFORMANCE_INFORMATION</c> structure that can be used to generate an unpredictable seed for a
/// random number generator. Use the CryptGenRandomfunction instead.
/// </para>
/// <para>SystemPolicyInformation</para>
/// <para>
/// Returns policy information in a <c>SYSTEM_POLICY_INFORMATION</c> structure. Use the SLGetWindowsInformation function instead to
/// obtain policy information.
/// </para>
/// <para>SystemProcessInformation</para>
/// <para>Returns an array of <c>SYSTEM_PROCESS_INFORMATION</c> structures, one for each process running in the system.</para>
/// <para>
/// These structures contain information about the resource usage of each process, including the number of threads and handles used
/// by the process, the peak page-file usage, and the number of memory pages that the process has allocated.
/// </para>
/// <para>SystemProcessorPerformanceInformation</para>
/// <para>
/// Returns an array of <c>SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION</c> structures, one for each processor installed in the system.
/// </para>
/// <para>SystemQueryPerformanceCounterInformation</para>
/// <para>
/// Returns a <c>SYSTEM_QUERY_PERFORMANCE_COUNTER_INFORMATION</c> structure that can be used to determine whether the system
/// requires a kernel transition to retrieve the high-resolution performance counter information through a QueryPerformanceCounter
/// function call.
/// </para>
/// <para>SystemRegistryQuotaInformation</para>
/// <para>Returns a <c>SYSTEM_REGISTRY_QUOTA_INFORMATION</c> structure.</para>
/// <para>SystemSpeculationControlInformation</para>
/// <para>
/// Returns a <c>SYSTEM_SPECULATION_CONTROL_INFORMATION</c> structure that can be used to determine the speculation control settings
/// for attacks involving branch target injection (such as CVE-2017-5715).
/// </para>
/// <para>SystemTimeOfDayInformation</para>
/// <para>
/// Returns an opaque <c>SYSTEM_TIMEOFDAY_INFORMATION</c> structure that can be used to generate an unpredictable seed for a random
/// number generator. Use the CryptGenRandom function instead.
/// </para>
/// </param>
/// <param name="SystemInformation">
/// <para>
/// A pointer to a buffer that receives the requested information. The size and structure of this information varies depending on
/// the value of the SystemInformationClass parameter:
/// </para>
/// <para>SYSTEM_BASIC_INFORMATION</para>
/// <para>
/// When the SystemInformationClass parameter is <c>SystemBasicInformation</c>, the buffer pointed to by the SystemInformation
/// parameter should be large enough to hold a single <c>SYSTEM_BASIC_INFORMATION</c> structure having the following layout:
/// </para>
/// <code>
///typedef struct _SYSTEM_BASIC_INFORMATION {
///BYTE Reserved1[24];
///PVOID Reserved2[4];
///CCHAR NumberOfProcessors;
///} SYSTEM_BASIC_INFORMATION;"
/// </code>
/// <para>
/// The <c>NumberOfProcessors</c> member contains the number of processors present in the system. Use GetSystemInfo instead to
/// retrieve this information.
/// </para>
/// <para>The other members of the structure are reserved for internal use by the operating system.</para>
/// <para>SYSTEM_CODEINTEGRITY_INFORMATION</para>
/// <para>
/// When the SystemInformationClass parameter is <c>SystemCodeIntegrityInformation</c>, the buffer pointed to by the
/// SystemInformation parameter should be large enough to hold a single <c>SYSTEM_CODEINTEGRITY_INFORMATION</c> structure having the
/// following layout:
/// </para>
/// <code>
///typedef struct _SYSTEM_CODEINTEGRITY_INFORMATION {
///ULONG Length;
///ULONG CodeIntegrityOptions;
///} SYSTEM_CODEINTEGRITY_INFORMATION, *PSYSTEM_CODEINTEGRITY_INFORMATION;"
/// </code>
/// <para>The <c>Length</c> member contains the size of the structure in bytes. This must be set by the caller.</para>
/// <para>The <c>CodeIntegrityOptions</c> member contains a bitmask to identify code integrity options.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term/>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>0x01</term>
/// <term>CODEINTEGRITY_OPTION_ENABLED</term>
/// <term>Enforcement of kernel mode Code Integrity is enabled.</term>
/// </item>
/// <item>
/// <term>0x02</term>
/// <term>CODEINTEGRITY_OPTION_TESTSIGN</term>
/// <term>Test signed content is allowed by Code Integrity.</term>
/// </item>
/// <item>
/// <term>0x04</term>
/// <term>CODEINTEGRITY_OPTION_UMCI_ENABLED</term>
/// <term>Enforcement of user mode Code Integrity is enabled.</term>
/// </item>
/// <item>
/// <term>0x08</term>
/// <term>CODEINTEGRITY_OPTION_UMCI_AUDITMODE_ENABLED</term>
/// <term>
/// Enforcement of user mode Code Integrity is enabled in audit mode. Executables will be allowed to run/load; however, audit events
/// will be recorded.
/// </term>
/// </item>
/// <item>
/// <term>0x10</term>
/// <term>CODEINTEGRITY_OPTION_UMCI_EXCLUSIONPATHS_ENABLED</term>
/// <term>
/// User mode binaries being run from certain paths are allowed to run even if they fail code integrity checks. Exclusion paths are
/// listed in the following registry key in REG_MULTI_SZ format: Paths added to this key should be in one of two formats: The
/// following paths are restricted and cannot be added as an exclusion: Built-in Path Exclusions: The following paths are excluded
/// by default. You don't need to specifically add these to path exclusions. This only applies on ARM (Windows Runtime).
/// </term>
/// </item>
/// <item>
/// <term>0x20</term>
/// <term>CODEINTEGRITY_OPTION_TEST_BUILD</term>
/// <term>The build of Code Integrity is from a test build.</term>
/// </item>
/// <item>
/// <term>0x40</term>
/// <term>CODEINTEGRITY_OPTION_PREPRODUCTION_BUILD</term>
/// <term>The build of Code Integrity is from a pre-production build.</term>
/// </item>
/// <item>
/// <term>0x80</term>
/// <term>CODEINTEGRITY_OPTION_DEBUGMODE_ENABLED</term>
/// <term>The kernel debugger is attached and Code Integrity may allow unsigned code to load.</term>
/// </item>
/// <item>
/// <term>0x100</term>
/// <term>CODEINTEGRITY_OPTION_FLIGHT_BUILD</term>
/// <term>The build of Code Integrity is from a flight build.</term>
/// </item>
/// <item>
/// <term>0x200</term>
/// <term>CODEINTEGRITY_OPTION_FLIGHTING_ENABLED</term>
/// <term>
/// Flight signed content is allowed by Code Integrity. Flight signed content is content signed by the Microsoft Development Root
/// Certificate Authority 2014.
/// </term>
/// </item>
/// <item>
/// <term>0x400</term>
/// <term>CODEINTEGRITY_OPTION_HVCI_KMCI_ENABLED</term>
/// <term>Hypervisor enforced Code Integrity is enabled for kernel mode components.</term>
/// </item>
/// <item>
/// <term>0x800</term>
/// <term>CODEINTEGRITY_OPTION_HVCI_KMCI_AUDITMODE_ENABLED</term>
/// <term>
/// Hypervisor enforced Code Integrity is enabled in audit mode. Audit events will be recorded for kernel mode components that are
/// not compatible with HVCI. This bit can be set whether CODEINTEGRITY_OPTION_HVCI_KMCI_ENABLED is set or not.
/// </term>
/// </item>
/// <item>
/// <term>0x1000</term>
/// <term>CODEINTEGRITY_OPTION_HVCI_KMCI_STRICTMODE_ENABLED</term>
/// <term>Hypervisor enforced Code Integrity is enabled for kernel mode components, but in strict mode.</term>
/// </item>
/// <item>
/// <term>0x2000</term>
/// <term>CODEINTEGRITY_OPTION_HVCI_IUM_ENABLED</term>
/// <term>Hypervisor enforced Code Integrity is enabled with enforcement of Isolated User Mode component signing.</term>
/// </item>
/// </list>
/// <para>SYSTEM_EXCEPTION_INFORMATION</para>
/// <para>
/// When the SystemInformationClass parameter is <c>SystemExceptionInformation</c>, the buffer pointed to by the SystemInformation
/// parameter should be large enough to hold an opaque <c>SYSTEM_EXCEPTION_INFORMATION</c> structure for use in generating an
/// unpredictable seed for a random number generator. For this purpose, the structure has the following layout:
/// </para>
/// <code>
///typedef struct _SYSTEM_EXCEPTION_INFORMATION {
///BYTE Reserved1[16];
///} SYSTEM_EXCEPTION_INFORMATION;
/// </code>
/// <para>Individual members of the structure are reserved for internal use by the operating system.</para>
/// <para>Use the CryptGenRandom function instead to generate cryptographically random data.</para>
/// <para>SYSTEM_INTERRUPT_INFORMATION</para>
/// <para>
/// When the SystemInformationClass parameter is <c>SystemInterruptInformation</c>, the buffer pointed to by the SystemInformation
/// parameter should be large enough to hold an array that contains as many opaque <c>SYSTEM_INTERRUPT_INFORMATION</c> structures as
/// there are processors (CPUs) installed on the system. Each structure, or the array as a whole, can be used to generate an
/// unpredictable seed for a random number generator. For this purpose, the structure has the following layout:
/// </para>
/// <code>
///typedef struct _SYSTEM_INTERRUPT_INFORMATION {
///BYTE Reserved1[24];
///} SYSTEM_INTERRUPT_INFORMATION;
/// </code>
/// <para>Individual members of the structure are reserved for internal use by the operating system.</para>
/// <para>Use the CryptGenRandom function instead to generate cryptographically random data.</para>
/// <para>SYSTEM_KERNEL_VA_SHADOW_INFORMATION</para>
/// <para>
/// When the SystemInformationClass parameter is <c>SystemKernelVaShadowInformation</c>, the buffer pointed to by the
/// SystemInformation parameter should be large enough to hold a single <c>SYSTEM_KERNEL_VA_SHADOW_INFORMATION</c> structure having
/// the following layout:
/// </para>
/// <code>
///typedef struct _SYSTEM_KERNEL_VA_SHADOW_INFORMATION {
///struct {
///ULONG KvaShadowEnabled:1;
///ULONG KvaShadowUserGlobal:1;
///ULONG KvaShadowPcid:1;
///ULONG KvaShadowInvpcid:1;
///ULONG Reserved:28;
///} KvaShadowFlags;
///} SYSTEM_KERNEL_VA_SHADOW_INFORMATION, * PSYSTEM_KERNEL_VA_SHADOW_INFORMATION;
/// </code>
/// <para>The <c>KvaShadowEnabled</c> indicates whether shadowing is enabled.</para>
/// <para>The <c>KvaShadowUserGlobal</c> indicates that user/global is enabled.</para>
/// <para>The <c>KvaShadowPcid</c> indicates whether PCID is enabled.</para>
/// <para>The <c>KvaShadowInvpcid</c> indicates whether PCID is enabled and whether INVPCID is in use.</para>
/// <para>The <c>Reserved</c> member of the structure is reserved for internal use by the operating system.</para>
/// <para>SYSTEM_LEAP_SECOND_INFORMATION</para>
/// <para>
/// When the SystemInformationClass parameter is <c>SystemLeapSecondInformation</c>, the buffer pointed to by the SystemInformation
/// parameter should be large enough to hold an opaque <c>SYSTEM_LEAP_SECOND_INFORMATION</c> structure for use in enabling or
/// disabling leap seconds system-wide. This setting will persist even after a reboot of the system. For this purpose, the structure
/// has the following layout:
/// </para>
/// <code>
///typedef struct _SYSTEM_LEAP_SECOND_INFORMATION {
///BOOLEAN Enabled;
///ULONG Flags;
///} SYSTEM_LEAP_SECOND_INFORMATION
/// </code>
/// <para>The <c>Flags</c> field is reserved for future use.</para>
/// <para>SYSTEM_LOOKASIDE_INFORMATION</para>
/// <para>
/// When the SystemInformationClass parameter is <c>SystemLookasideInformation</c>, the buffer pointed to by the SystemInformation
/// parameter should be large enough to hold an opaque <c>SYSTEM_LOOKASIDE_INFORMATION</c> structure for use in generating an
/// unpredictable seed for a random number generator. For this purpose, the structure has the following layout:
/// </para>
/// <code>
///typedef struct _SYSTEM_LOOKASIDE_INFORMATION {
///BYTE Reserved1[32];
///} SYSTEM_LOOKASIDE_INFORMATION;
/// </code>
/// <para>Individual members of the structure are reserved for internal use by the operating system.</para>
/// <para>Use the CryptGenRandom function instead to generate cryptographically random data.</para>
/// <para>SYSTEM_PERFORMANCE_INFORMATION</para>
/// <para>
/// When the SystemInformationClass parameter is <c>SystemPerformanceInformation</c>, the buffer pointed to by the SystemInformation
/// parameter should be large enough to hold an opaque <c>SYSTEM_PERFORMANCE_INFORMATION</c> structure for use in generating an
/// unpredictable seed for a random number generator. For this purpose, the structure has the following layout:
/// </para>
/// <code>
///typedef struct _SYSTEM_PERFORMANCE_INFORMATION {
///BYTE Reserved1[312];
///} SYSTEM_PERFORMANCE_INFORMATION;
/// </code>
/// <para>Individual members of the structure are reserved for internal use by the operating system.</para>
/// <para>Use the CryptGenRandom function instead to generate cryptographically random data.</para>
/// <para>SYSTEM_POLICY_INFORMATION</para>
/// <para>
/// When the SystemInformationClass parameter is <c>SystemPolicyInformation</c>, the buffer pointed to by the SystemInformation
/// parameter should be large enough to hold a single <c>SYSTEM_POLICY_INFORMATION</c> structure having the following layout:
/// </para>
/// <code>
///typedef struct _SYSTEM_POLICY_INFORMATION {
///PVOID Reserved1[2];
///ULONG Reserved2[3];
///} SYSTEM_POLICY_INFORMATION;
/// </code>
/// <para>Individual members of the structure are reserved for internal use by the operating system.</para>
/// <para>Use the SLGetWindowsInformation function instead to obtain policy information.</para>
/// <para>SYSTEM_PROCESS_INFORMATION</para>
/// <para>
/// When the SystemInformationClass parameter is <c>SystemProcessInformation</c>, the buffer pointed to by the SystemInformation
/// parameter contains a <c>SYSTEM_PROCESS_INFORMATION</c> structure for each process. Each of these structures is immediately
/// followed in memory by one or more <c>SYSTEM_THREAD_INFORMATION</c> structures that provide info for each thread in the preceding
/// process. For more information about <c>SYSTEM_THREAD_INFORMATION</c>, see the section about this structure in this article.
/// </para>
/// <para>
/// The buffer pointed to by the SystemInformation parameter should be large enough to hold an array that contains as many
/// <c>SYSTEM_PROCESS_INFORMATION</c> and <c>SYSTEM_THREAD_INFORMATION</c> structures as there are processes and threads running in
/// the system. This size is specified by the ReturnLength parameter.
/// </para>
/// <para>Each <c>SYSTEM_PROCESS_INFORMATION</c> structure has the following layout:</para>
/// <code>
///typedef struct _SYSTEM_PROCESS_INFORMATION {
///ULONG NextEntryOffset;
///ULONG NumberOfThreads;
///BYTE Reserved1[48];
///UNICODE_STRING ImageName;
///KPRIORITY BasePriority;
///HANDLE UniqueProcessId;
///PVOID Reserved2;
///ULONG HandleCount;
///ULONG SessionId;
///PVOID Reserved3;
///SIZE_T PeakVirtualSize;
///SIZE_T VirtualSize;
///ULONG Reserved4;
///SIZE_T PeakWorkingSetSize;
///SIZE_T WorkingSetSize;
///PVOID Reserved5;
///SIZE_T QuotaPagedPoolUsage;
///PVOID Reserved6;
///SIZE_T QuotaNonPagedPoolUsage;
///SIZE_T PagefileUsage;
///SIZE_T PeakPagefileUsage;
///SIZE_T PrivatePageCount;
///LARGE_INTEGER Reserved7[6];
///} SYSTEM_PROCESS_INFORMATION;
/// </code>
/// <para>
/// The start of the next item in the array is the address of the previous item plus the value in the <c>NextEntryOffset</c> member.
/// For the last item in the array, <c>NextEntryOffset</c> is 0.
/// </para>
/// <para>The <c>NumberOfThreads</c> member contains the number of threads in the process.</para>
/// <para>The <c>ImageName</c> member contains the process's image name.</para>
/// <para>
/// The <c>BasePriority</c> member contains the base priority of the process, which is the starting priority for threads created
/// within the associated process.
/// </para>
/// <para>The <c>UniqueProcessId</c> member contains the process's unique process ID.</para>
/// <para>
/// The <c>HandleCount</c> member contains the total number of handles being used by the process in question; use
/// GetProcessHandleCount to retrieve this information instead.
/// </para>
/// <para>The <c>SessionId</c> member contains the session identifier of the process session.</para>
/// <para>The <c>PeakVirtualSize</c> member contains the peak size, in bytes, of the virtual memory used by the process.</para>
/// <para>The <c>VirtualSize</c> member contains the current size, in bytes, of virtual memory used by the process.</para>
/// <para>The <c>PeakWorkingSetSize</c> member contains the peak size, in kilobytes, of the working set of the process.</para>
/// <para>The <c>QuotaPagedPoolUsage</c> member contains the current quota charged to the process for paged pool usage.</para>
/// <para>The <c>QuotaNonPagedPoolUsage</c> member contains the current quota charged to the process for nonpaged pool usage.</para>
/// <para>The <c>PagefileUsage</c> member contains the number of bytes of page file storage in use by the process.</para>
/// <para>The <c>PeakPagefileUsage</c> member contains the maximum number of bytes of page-file storage used by the process.</para>
/// <para>The <c>PrivatePageCount</c> member contains the number of memory pages allocated for the use of this process.</para>
/// <para>
/// You can also retrieve the <c>PeakWorkingSetSize</c>, <c>QuotaPagedPoolUsage</c>, <c>QuotaNonPagedPoolUsage</c>,
/// <c>PagefileUsage</c>, <c>PeakPagefileUsage</c>, and <c>PrivatePageCount</c> information using either the GetProcessMemoryInfo
/// function or the Win32_Process class.
/// </para>
/// <para>The other members of the structure are reserved for internal use by the operating system.</para>
/// <para>SYSTEM_THREAD_INFORMATION</para>
/// <para>
/// When the SystemInformationClass parameter is <c>SystemProcessInformation</c>, the buffer pointed to by the SystemInformation
/// parameter contains a <c>SYSTEM_PROCESS_INFORMATION</c> structure for each process. Each of these structures is immediately
/// followed in memory by one or more <c>SYSTEM_THREAD_INFORMATION</c> structures that provide info for each thread in the preceding
/// process. For more information about <c>SYSTEM_PROCESS_INFORMATION</c>, see the section about this structure in this article.
/// Each <c>SYSTEM_THREAD_INFORMATION</c> structure has the following layout:
/// </para>
/// <code>
///typedef struct _SYSTEM_THREAD_INFORMATION {
///LARGE_INTEGER Reserved1[3];
///ULONG Reserved2;
///PVOID StartAddress;
///CLIENT_ID ClientId;
///KPRIORITY Priority;
///LONG BasePriority;
///ULONG Reserved3;
///ULONG ThreadState;
///ULONG WaitReason;
///} SYSTEM_THREAD_INFORMATION;
/// </code>
/// <para>The <c>StartAddress</c> member contains the start address of the thread.</para>
/// <para>The <c>ClientId</c> member contains the ID of the thread and the process owning the thread.</para>
/// <para>The <c>Priority</c> member contains the dynamic thread priority.</para>
/// <para>The <c>BasePriority</c> member contains the base thread priority.</para>
/// <para>The <c>ThreadState</c> member contains the current thread state.</para>
/// <para>The <c>WaitReason</c> member contains the reason the thread is waiting.</para>
/// <para>The other members of the structure are reserved for internal use by the operating system.</para>
/// <para>SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION</para>
/// <para>
/// When the SystemInformationClass parameter is <c>SystemProcessorPerformanceInformation</c>, the buffer pointed to by the
/// SystemInformation parameter should be large enough to hold an array that contains as many
/// <c>SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION</c> structures as there are processors (CPUs) installed in the system. Each
/// structure has the following layout:
/// </para>
/// <code>
///typedef struct
///_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION {
///LARGE_INTEGER IdleTime;
///LARGE_INTEGER KernelTime;
///LARGE_INTEGER UserTime;
///LARGE_INTEGER Reserved1[2];
///ULONG Reserved2;
///} SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION;
/// </code>
/// <para>The <c>IdleTime</c> member contains the amount of time that the system has been idle, in 100-nanosecond intervals.</para>
/// <para>
/// The <c>KernelTime</c> member contains the amount of time that the system has spent executing in Kernel mode (including all
/// threads in all processes, on all processors), in 100-nanosecond intervals.
/// </para>
/// <para>
/// The <c>UserTime</c> member contains the amount of time that the system has spent executing in User mode (including all threads
/// in all processes, on all processors), in 100-nanosecond intervals.
/// </para>
/// <para>Use GetSystemTimesinstead to retrieve this information.</para>
/// <para>SYSTEM_QUERY_PERFORMANCE_COUNTER_INFORMATION</para>
/// <para>
/// When the SystemInformationClass parameter is <c>SystemQueryPerformanceCounterInformation</c>, the buffer pointed to by the
/// SystemInformation parameter should be large enough to hold a single <c>SYSTEM_QUERY_PERFORMANCE_COUNTER_INFORMATION</c>
/// structure having the following layout:
/// </para>
/// <code>
///typedef struct _SYSTEM_QUERY_PERFORMANCE_COUNTER_INFORMATION {
///ULONG Version;
///QUERY_PERFORMANCE_COUNTER_FLAGS Flags;
///QUERY_PERFORMANCE_COUNTER_FLAGS ValidFlags;
///} SYSTEM_QUERY_PERFORMANCE_COUNTER_INFORMATION;
/// </code>
/// <para>
/// The <c>Flags</c> and <c>ValidFlags</c> members are <c>QUERY_PERFORMANCE_COUNTER_FLAGS</c> structures having the following layout:
/// </para>
/// <code>
///typedef struct _QUERY_PERFORMANCE_COUNTER_FLAGS {
///union {
///struct {
///ULONG KernelTransition:1;
///ULONG Reserved:31;
///};
///ULONG ul;
///};
///} QUERY_PERFORMANCE_COUNTER_FLAGS;
/// </code>
/// <para>
/// The <c>ValidFlags</c> member of the <c>SYSTEM_QUERY_PERFORMANCE_COUNTER_INFORMATION</c> structure indicates which bits of the
/// <c>Flags</c> member contain valid information. If a kernel transition is required, the <c>KernelTransition</c> bit is set in
/// both <c>ValidFlags</c> and <c>Flags</c>. If a kernel transition is not required, the <c>KernelTransition</c> bit is set in
/// <c>ValidFlags</c> and clear in <c>Flags</c>.
/// </para>
/// <para>SYSTEM_REGISTRY_QUOTA_INFORMATION</para>
/// <para>
/// When the SystemInformationClass parameter is <c>SystemRegistryQuotaInformation</c>, the buffer pointed to by the
/// SystemInformation parameter should be large enough to hold a single <c>SYSTEM_REGISTRY_QUOTA_INFORMATION</c> structure having
/// the following layout:
/// </para>
/// <code>
///typedef struct _SYSTEM_REGISTRY_QUOTA_INFORMATION {
///ULONG RegistryQuotaAllowed;
///ULONG RegistryQuotaUsed;
///PVOID Reserved1;
///} SYSTEM_REGISTRY_QUOTA_INFORMATION;
/// </code>
/// <para>The <c>RegistryQuotaAllowed</c> member contains the maximum size, in bytes, that the Registry can attain on this system.</para>
/// <para>The <c>RegistryQuotaUsed</c> member contains the current size of the Registry, in bytes.</para>
/// <para>Use GetSystemRegistryQuota instead to retrieve this information.</para>
/// <para>The other member of the structure is reserved for internal use by the operating system.</para>
/// <para>SYSTEM_SPECULATION_CONTROL_INFORMATION</para>
/// <para>
/// When the SystemInformationClass parameter is <c>SystemSpeculationControlInformation</c>, the buffer pointed to by the
/// SystemInformation parameter should be large enough to hold a single <c>SYSTEM_SPECULATION_CONTROL_INFORMATION</c> structure
/// having the following layout:
/// </para>
/// <code>
///typedef struct _SYSTEM_SPECULATION_CONTROL_INFORMATION {
///struct {
///ULONG BpbEnabled:1;
///ULONG BpbDisabledSystemPolicy:1;
///ULONG BpbDisabledNoHardwareSupport:1;
///ULONG SpecCtrlEnumerated:1;
///ULONG SpecCmdEnumerated:1;
///ULONG IbrsPresent:1;
///ULONG StibpPresent:1;
///ULONG SmepPresent:1;
///ULONG Reserved:24;
///} SpeculationControlFlags;
///
///} SYSTEM_SPECULATION_CONTROL_INFORMATION, * PSYSTEM_SPECULATION_CONTROL_INFORMATION;
/// </code>
/// <para>The <c>BpbEnabled</c> indicates whether speculation control features are supported and enabled.</para>
/// <para>The <c>BpbDisabledSystemPolicy</c> indicates whether speculation control features are disabled due to system policy.</para>
/// <para>
/// The <c>BpbDisabledNoHardwareSupport</c> whether speculation control features are disabled due to the absence of hardware support.
/// </para>
/// <para>The <c>SpecCtrlEnumerated</c> whether the IA32_SPEC_CTRL MSR is enumerated by hardware.</para>
/// <para>The <c>SpecCmdEnumerated</c> indicates whether the IA32_SPEC_CMD MSR is enumerated by hardware.</para>
/// <para>The <c>IbrsPresent</c> indicates whether the IBRS MSR is treated as being present.</para>
/// <para>The <c>StibpPresent</c> indicates whether the STIBP MSR is present.</para>
/// <para>The <c>SmepPresent</c> indicates whether the SMEP feature is present and enabled.</para>
/// <para>The <c>Reserved</c> member of the structure is reserved for internal use by the operating system.</para>
/// <para>SYSTEM_TIMEOFDAY_INFORMATION</para>
/// <para>
/// When the SystemInformationClass parameter is <c>SystemTimeOfDayInformation</c>, the buffer pointed to by the SystemInformation
/// parameter should be large enough to hold an opaque <c>SYSTEM_TIMEOFDAY_INFORMATION</c> structure for use in generating an
/// unpredictable seed for a random number generator. For this purpose, the structure has the following layout:
/// </para>
/// <code>
///typedef struct _SYSTEM_TIMEOFDAY_INFORMATION {
///BYTE Reserved1[48];
///} SYSTEM_TIMEOFDAY_INFORMATION;
/// </code>
/// <para>Individual members of the structure are reserved for internal use by the operating system.</para>
/// <para>Use the CryptGenRandom function instead to generate cryptographically random data.</para>
/// </param>
/// <param name="SystemInformationLength">
/// <para>The size of the buffer pointed to by the SystemInformationparameter, in bytes.</para>
/// </param>
/// <param name="ReturnLength"/>
/// <returns>
/// <para>Returns an NTSTATUS success or error code.</para>
/// <para>
/// The forms and significance of NTSTATUS error codes are listed in the Ntstatus.h header file available in the DDK, and are
/// described in the DDK documentation.
/// </para>
/// </returns>
/// <remarks>
/// <para>
/// The <c>NtQuerySystemInformation</c> function and the structures that it returns are internal to the operating system and subject
/// to change from one release of Windows to another. To maintain the compatibility of your application, it is better to use the
/// alternate functions previously mentioned instead.
/// </para>
/// <para>
/// If you do use <c>NtQuerySystemInformation</c>, access the function through run-time dynamic linking. This gives your code an
/// opportunity to respond gracefully if the function has been changed or removed from the operating system. Signature changes,
/// however, may not be detectable.
/// </para>
/// <para>
/// This function has no associated import library. You must use the LoadLibrary and GetProcAddress functions to dynamically link to Ntdll.dll.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winternl/nf-winternl-ntquerysysteminformation __kernel_entry NTSTATUS
// NtQuerySystemInformation( IN SYSTEM_INFORMATION_CLASS SystemInformationClass, OUT PVOID SystemInformation, IN ULONG
// SystemInformationLength, OUT PULONG ReturnLength OPTIONAL );
[DllImport(Lib.NtDll, SetLastError = false, ExactSpelling = true)]
[PInvokeData("winternl.h", MSDNShortId = "553ec7b9-c5eb-4955-8dc0-f1c06f59fe31")]
public static extern NTStatus NtQuerySystemInformation(SYSTEM_INFORMATION_CLASS SystemInformationClass, SafeHGlobalHandle SystemInformation, uint SystemInformationLength, out uint ReturnLength);
/// <summary>
/// <para>
/// [ <c>NtQuerySystemInformation</c> may be altered or unavailable in future versions of Windows. Applications should use the
/// alternate functions listed in this topic.]
/// </para>
/// <para>Retrieves the specified system information.</para>
/// </summary>
/// <typeparam name="T">The type of the return value.</typeparam>
/// <param name="SystemInformationClass">
/// <para>
/// One of the values enumerated in SYSTEM_INFORMATION_CLASS, which indicate the kind of system information to be retrieved. These
/// include the following values.
/// </para>
/// <para>SystemBasicInformation</para>
/// <para>
/// Returns the number of processors in the system in a <c>SYSTEM_BASIC_INFORMATION</c> structure. Use the GetSystemInfo function instead.
/// </para>
/// <para>SystemCodeIntegrityInformation</para>
/// <para>
/// Returns a <c>SYSTEM_CODEINTEGRITY_INFORMATION</c> structure that can be used to determine the options being enforced by Code
/// Integrity on the system.
/// </para>
/// <para>SystemExceptionInformation</para>
/// <para>
/// Returns an opaque <c>SYSTEM_EXCEPTION_INFORMATION</c> structure that can be used to generate an unpredictable seed for a random
/// number generator. Use the CryptGenRandom function instead.
/// </para>
/// <para>SystemInterruptInformation</para>
/// <para>
/// Returns an opaque <c>SYSTEM_INTERRUPT_INFORMATION</c> structure that can be used to generate an unpredictable seed for a random
/// number generator. Use the CryptGenRandom function instead.
/// </para>
/// <para>SystemKernelVaShadowInformation</para>
/// <para>
/// Returns a <c>SYSTEM_KERNEL_VA_SHADOW_INFORMATION</c> structure that can be used to determine the speculation control settings
/// for attacks involving rogue data cache loads (such as CVE-2017-5754).
/// </para>
/// <para>SystemLeapSecondInformation</para>
/// <para>
/// Returns an opaque <c>SYSTEM_LEAP_SECOND_INFORMATION</c> structure that can be used to enable or disable leap seconds
/// system-wide. This setting will persist even after a reboot of the system.
/// </para>
/// <para>SystemLookasideInformation</para>
/// <para>
/// Returns an opaque <c>SYSTEM_LOOKASIDE_INFORMATION</c> structure that can be used to generate an unpredictable seed for a random
/// number generator. Use the CryptGenRandom function instead.
/// </para>
/// <para>SystemPerformanceInformation</para>
/// <para>
/// Returns an opaque <c>SYSTEM_PERFORMANCE_INFORMATION</c> structure that can be used to generate an unpredictable seed for a
/// random number generator. Use the CryptGenRandomfunction instead.
/// </para>
/// <para>SystemPolicyInformation</para>
/// <para>
/// Returns policy information in a <c>SYSTEM_POLICY_INFORMATION</c> structure. Use the SLGetWindowsInformation function instead to
/// obtain policy information.
/// </para>
/// <para>SystemProcessInformation</para>
/// <para>Returns an array of <c>SYSTEM_PROCESS_INFORMATION</c> structures, one for each process running in the system.</para>
/// <para>
/// These structures contain information about the resource usage of each process, including the number of threads and handles used
/// by the process, the peak page-file usage, and the number of memory pages that the process has allocated.
/// </para>
/// <para>SystemProcessorPerformanceInformation</para>
/// <para>
/// Returns an array of <c>SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION</c> structures, one for each processor installed in the system.
/// </para>
/// <para>SystemQueryPerformanceCounterInformation</para>
/// <para>
/// Returns a <c>SYSTEM_QUERY_PERFORMANCE_COUNTER_INFORMATION</c> structure that can be used to determine whether the system
/// requires a kernel transition to retrieve the high-resolution performance counter information through a QueryPerformanceCounter
/// function call.
/// </para>
/// <para>SystemRegistryQuotaInformation</para>
/// <para>Returns a <c>SYSTEM_REGISTRY_QUOTA_INFORMATION</c> structure.</para>
/// <para>SystemSpeculationControlInformation</para>
/// <para>
/// Returns a <c>SYSTEM_SPECULATION_CONTROL_INFORMATION</c> structure that can be used to determine the speculation control settings
/// for attacks involving branch target injection (such as CVE-2017-5715).
/// </para>
/// <para>SystemTimeOfDayInformation</para>
/// <para>
/// Returns an opaque <c>SYSTEM_TIMEOFDAY_INFORMATION</c> structure that can be used to generate an unpredictable seed for a random
/// number generator. Use the CryptGenRandom function instead.
/// </para>
/// </param>
/// <returns>
/// <para>
/// A pointer to a buffer that receives the requested information. The size and structure of this information varies depending on
/// the value of the SystemInformationClass parameter:
/// </para>
/// <para>SYSTEM_BASIC_INFORMATION</para>
/// <para>
/// When the SystemInformationClass parameter is <c>SystemBasicInformation</c>, the buffer pointed to by the SystemInformation
/// parameter should be large enough to hold a single <c>SYSTEM_BASIC_INFORMATION</c> structure having the following layout:
/// </para>
/// <code>
///typedef struct _SYSTEM_BASIC_INFORMATION {
///BYTE Reserved1[24];
///PVOID Reserved2[4];
///CCHAR NumberOfProcessors;
///} SYSTEM_BASIC_INFORMATION;"
/// </code>
/// <para>
/// The <c>NumberOfProcessors</c> member contains the number of processors present in the system. Use GetSystemInfo instead to
/// retrieve this information.
/// </para>
/// <para>The other members of the structure are reserved for internal use by the operating system.</para>
/// <para>SYSTEM_CODEINTEGRITY_INFORMATION</para>
/// <para>
/// When the SystemInformationClass parameter is <c>SystemCodeIntegrityInformation</c>, the buffer pointed to by the
/// SystemInformation parameter should be large enough to hold a single <c>SYSTEM_CODEINTEGRITY_INFORMATION</c> structure having the
/// following layout:
/// </para>
/// <code>
///typedef struct _SYSTEM_CODEINTEGRITY_INFORMATION {
///ULONG Length;
///ULONG CodeIntegrityOptions;
///} SYSTEM_CODEINTEGRITY_INFORMATION, *PSYSTEM_CODEINTEGRITY_INFORMATION;"
/// </code>
/// <para>The <c>Length</c> member contains the size of the structure in bytes. This must be set by the caller.</para>
/// <para>The <c>CodeIntegrityOptions</c> member contains a bitmask to identify code integrity options.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term/>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>0x01</term>
/// <term>CODEINTEGRITY_OPTION_ENABLED</term>
/// <term>Enforcement of kernel mode Code Integrity is enabled.</term>
/// </item>
/// <item>
/// <term>0x02</term>
/// <term>CODEINTEGRITY_OPTION_TESTSIGN</term>
/// <term>Test signed content is allowed by Code Integrity.</term>
/// </item>
/// <item>
/// <term>0x04</term>
/// <term>CODEINTEGRITY_OPTION_UMCI_ENABLED</term>
/// <term>Enforcement of user mode Code Integrity is enabled.</term>
/// </item>
/// <item>
/// <term>0x08</term>
/// <term>CODEINTEGRITY_OPTION_UMCI_AUDITMODE_ENABLED</term>
/// <term>
/// Enforcement of user mode Code Integrity is enabled in audit mode. Executables will be allowed to run/load; however, audit events
/// will be recorded.
/// </term>
/// </item>
/// <item>
/// <term>0x10</term>
/// <term>CODEINTEGRITY_OPTION_UMCI_EXCLUSIONPATHS_ENABLED</term>
/// <term>
/// User mode binaries being run from certain paths are allowed to run even if they fail code integrity checks. Exclusion paths are
/// listed in the following registry key in REG_MULTI_SZ format: Paths added to this key should be in one of two formats: The
/// following paths are restricted and cannot be added as an exclusion: Built-in Path Exclusions: The following paths are excluded
/// by default. You don't need to specifically add these to path exclusions. This only applies on ARM (Windows Runtime).
/// </term>
/// </item>
/// <item>
/// <term>0x20</term>
/// <term>CODEINTEGRITY_OPTION_TEST_BUILD</term>
/// <term>The build of Code Integrity is from a test build.</term>
/// </item>
/// <item>
/// <term>0x40</term>
/// <term>CODEINTEGRITY_OPTION_PREPRODUCTION_BUILD</term>
/// <term>The build of Code Integrity is from a pre-production build.</term>
/// </item>
/// <item>
/// <term>0x80</term>
/// <term>CODEINTEGRITY_OPTION_DEBUGMODE_ENABLED</term>
/// <term>The kernel debugger is attached and Code Integrity may allow unsigned code to load.</term>
/// </item>
/// <item>
/// <term>0x100</term>
/// <term>CODEINTEGRITY_OPTION_FLIGHT_BUILD</term>
/// <term>The build of Code Integrity is from a flight build.</term>
/// </item>
/// <item>
/// <term>0x200</term>
/// <term>CODEINTEGRITY_OPTION_FLIGHTING_ENABLED</term>
/// <term>
/// Flight signed content is allowed by Code Integrity. Flight signed content is content signed by the Microsoft Development Root
/// Certificate Authority 2014.
/// </term>
/// </item>
/// <item>
/// <term>0x400</term>
/// <term>CODEINTEGRITY_OPTION_HVCI_KMCI_ENABLED</term>
/// <term>Hypervisor enforced Code Integrity is enabled for kernel mode components.</term>
/// </item>
/// <item>
/// <term>0x800</term>
/// <term>CODEINTEGRITY_OPTION_HVCI_KMCI_AUDITMODE_ENABLED</term>
/// <term>
/// Hypervisor enforced Code Integrity is enabled in audit mode. Audit events will be recorded for kernel mode components that are
/// not compatible with HVCI. This bit can be set whether CODEINTEGRITY_OPTION_HVCI_KMCI_ENABLED is set or not.
/// </term>
/// </item>
/// <item>
/// <term>0x1000</term>
/// <term>CODEINTEGRITY_OPTION_HVCI_KMCI_STRICTMODE_ENABLED</term>
/// <term>Hypervisor enforced Code Integrity is enabled for kernel mode components, but in strict mode.</term>
/// </item>
/// <item>
/// <term>0x2000</term>
/// <term>CODEINTEGRITY_OPTION_HVCI_IUM_ENABLED</term>
/// <term>Hypervisor enforced Code Integrity is enabled with enforcement of Isolated User Mode component signing.</term>
/// </item>
/// </list>
/// <para>SYSTEM_EXCEPTION_INFORMATION</para>
/// <para>
/// When the SystemInformationClass parameter is <c>SystemExceptionInformation</c>, the buffer pointed to by the SystemInformation
/// parameter should be large enough to hold an opaque <c>SYSTEM_EXCEPTION_INFORMATION</c> structure for use in generating an
/// unpredictable seed for a random number generator. For this purpose, the structure has the following layout:
/// </para>
/// <code>
///typedef struct _SYSTEM_EXCEPTION_INFORMATION {
///BYTE Reserved1[16];
///} SYSTEM_EXCEPTION_INFORMATION;
/// </code>
/// <para>Individual members of the structure are reserved for internal use by the operating system.</para>
/// <para>Use the CryptGenRandom function instead to generate cryptographically random data.</para>
/// <para>SYSTEM_INTERRUPT_INFORMATION</para>
/// <para>
/// When the SystemInformationClass parameter is <c>SystemInterruptInformation</c>, the buffer pointed to by the SystemInformation
/// parameter should be large enough to hold an array that contains as many opaque <c>SYSTEM_INTERRUPT_INFORMATION</c> structures as
/// there are processors (CPUs) installed on the system. Each structure, or the array as a whole, can be used to generate an
/// unpredictable seed for a random number generator. For this purpose, the structure has the following layout:
/// </para>
/// <code>
///typedef struct _SYSTEM_INTERRUPT_INFORMATION {
///BYTE Reserved1[24];
///} SYSTEM_INTERRUPT_INFORMATION;
/// </code>
/// <para>Individual members of the structure are reserved for internal use by the operating system.</para>
/// <para>Use the CryptGenRandom function instead to generate cryptographically random data.</para>
/// <para>SYSTEM_KERNEL_VA_SHADOW_INFORMATION</para>
/// <para>
/// When the SystemInformationClass parameter is <c>SystemKernelVaShadowInformation</c>, the buffer pointed to by the
/// SystemInformation parameter should be large enough to hold a single <c>SYSTEM_KERNEL_VA_SHADOW_INFORMATION</c> structure having
/// the following layout:
/// </para>
/// <code>
///typedef struct _SYSTEM_KERNEL_VA_SHADOW_INFORMATION {
///struct {
///ULONG KvaShadowEnabled:1;
///ULONG KvaShadowUserGlobal:1;
///ULONG KvaShadowPcid:1;
///ULONG KvaShadowInvpcid:1;
///ULONG Reserved:28;
///} KvaShadowFlags;
///} SYSTEM_KERNEL_VA_SHADOW_INFORMATION, * PSYSTEM_KERNEL_VA_SHADOW_INFORMATION;
/// </code>
/// <para>The <c>KvaShadowEnabled</c> indicates whether shadowing is enabled.</para>
/// <para>The <c>KvaShadowUserGlobal</c> indicates that user/global is enabled.</para>
/// <para>The <c>KvaShadowPcid</c> indicates whether PCID is enabled.</para>
/// <para>The <c>KvaShadowInvpcid</c> indicates whether PCID is enabled and whether INVPCID is in use.</para>
/// <para>The <c>Reserved</c> member of the structure is reserved for internal use by the operating system.</para>
/// <para>SYSTEM_LEAP_SECOND_INFORMATION</para>
/// <para>
/// When the SystemInformationClass parameter is <c>SystemLeapSecondInformation</c>, the buffer pointed to by the SystemInformation
/// parameter should be large enough to hold an opaque <c>SYSTEM_LEAP_SECOND_INFORMATION</c> structure for use in enabling or
/// disabling leap seconds system-wide. This setting will persist even after a reboot of the system. For this purpose, the structure
/// has the following layout:
/// </para>
/// <code>
///typedef struct _SYSTEM_LEAP_SECOND_INFORMATION {
///BOOLEAN Enabled;
///ULONG Flags;
///} SYSTEM_LEAP_SECOND_INFORMATION
/// </code>
/// <para>The <c>Flags</c> field is reserved for future use.</para>
/// <para>SYSTEM_LOOKASIDE_INFORMATION</para>
/// <para>
/// When the SystemInformationClass parameter is <c>SystemLookasideInformation</c>, the buffer pointed to by the SystemInformation
/// parameter should be large enough to hold an opaque <c>SYSTEM_LOOKASIDE_INFORMATION</c> structure for use in generating an
/// unpredictable seed for a random number generator. For this purpose, the structure has the following layout:
/// </para>
/// <code>
///typedef struct _SYSTEM_LOOKASIDE_INFORMATION {
///BYTE Reserved1[32];
///} SYSTEM_LOOKASIDE_INFORMATION;
/// </code>
/// <para>Individual members of the structure are reserved for internal use by the operating system.</para>
/// <para>Use the CryptGenRandom function instead to generate cryptographically random data.</para>
/// <para>SYSTEM_PERFORMANCE_INFORMATION</para>
/// <para>
/// When the SystemInformationClass parameter is <c>SystemPerformanceInformation</c>, the buffer pointed to by the SystemInformation
/// parameter should be large enough to hold an opaque <c>SYSTEM_PERFORMANCE_INFORMATION</c> structure for use in generating an
/// unpredictable seed for a random number generator. For this purpose, the structure has the following layout:
/// </para>
/// <code>
///typedef struct _SYSTEM_PERFORMANCE_INFORMATION {
///BYTE Reserved1[312];
///} SYSTEM_PERFORMANCE_INFORMATION;
/// </code>
/// <para>Individual members of the structure are reserved for internal use by the operating system.</para>
/// <para>Use the CryptGenRandom function instead to generate cryptographically random data.</para>
/// <para>SYSTEM_POLICY_INFORMATION</para>
/// <para>
/// When the SystemInformationClass parameter is <c>SystemPolicyInformation</c>, the buffer pointed to by the SystemInformation
/// parameter should be large enough to hold a single <c>SYSTEM_POLICY_INFORMATION</c> structure having the following layout:
/// </para>
/// <code>
///typedef struct _SYSTEM_POLICY_INFORMATION {
///PVOID Reserved1[2];
///ULONG Reserved2[3];
///} SYSTEM_POLICY_INFORMATION;
/// </code>
/// <para>Individual members of the structure are reserved for internal use by the operating system.</para>
/// <para>Use the SLGetWindowsInformation function instead to obtain policy information.</para>
/// <para>SYSTEM_PROCESS_INFORMATION</para>
/// <para>
/// When the SystemInformationClass parameter is <c>SystemProcessInformation</c>, the buffer pointed to by the SystemInformation
/// parameter contains a <c>SYSTEM_PROCESS_INFORMATION</c> structure for each process. Each of these structures is immediately
/// followed in memory by one or more <c>SYSTEM_THREAD_INFORMATION</c> structures that provide info for each thread in the preceding
/// process. For more information about <c>SYSTEM_THREAD_INFORMATION</c>, see the section about this structure in this article.
/// </para>
/// <para>
/// The buffer pointed to by the SystemInformation parameter should be large enough to hold an array that contains as many
/// <c>SYSTEM_PROCESS_INFORMATION</c> and <c>SYSTEM_THREAD_INFORMATION</c> structures as there are processes and threads running in
/// the system. This size is specified by the ReturnLength parameter.
/// </para>
/// <para>Each <c>SYSTEM_PROCESS_INFORMATION</c> structure has the following layout:</para>
/// <code>
///typedef struct _SYSTEM_PROCESS_INFORMATION {
///ULONG NextEntryOffset;
///ULONG NumberOfThreads;
///BYTE Reserved1[48];
///UNICODE_STRING ImageName;
///KPRIORITY BasePriority;
///HANDLE UniqueProcessId;
///PVOID Reserved2;
///ULONG HandleCount;
///ULONG SessionId;
///PVOID Reserved3;
///SIZE_T PeakVirtualSize;
///SIZE_T VirtualSize;
///ULONG Reserved4;
///SIZE_T PeakWorkingSetSize;
///SIZE_T WorkingSetSize;
///PVOID Reserved5;
///SIZE_T QuotaPagedPoolUsage;
///PVOID Reserved6;
///SIZE_T QuotaNonPagedPoolUsage;
///SIZE_T PagefileUsage;
///SIZE_T PeakPagefileUsage;
///SIZE_T PrivatePageCount;
///LARGE_INTEGER Reserved7[6];
///} SYSTEM_PROCESS_INFORMATION;
/// </code>
/// <para>
/// The start of the next item in the array is the address of the previous item plus the value in the <c>NextEntryOffset</c> member.
/// For the last item in the array, <c>NextEntryOffset</c> is 0.
/// </para>
/// <para>The <c>NumberOfThreads</c> member contains the number of threads in the process.</para>
/// <para>The <c>ImageName</c> member contains the process's image name.</para>
/// <para>
/// The <c>BasePriority</c> member contains the base priority of the process, which is the starting priority for threads created
/// within the associated process.
/// </para>
/// <para>The <c>UniqueProcessId</c> member contains the process's unique process ID.</para>
/// <para>
/// The <c>HandleCount</c> member contains the total number of handles being used by the process in question; use
/// GetProcessHandleCount to retrieve this information instead.
/// </para>
/// <para>The <c>SessionId</c> member contains the session identifier of the process session.</para>
/// <para>The <c>PeakVirtualSize</c> member contains the peak size, in bytes, of the virtual memory used by the process.</para>
/// <para>The <c>VirtualSize</c> member contains the current size, in bytes, of virtual memory used by the process.</para>
/// <para>The <c>PeakWorkingSetSize</c> member contains the peak size, in kilobytes, of the working set of the process.</para>
/// <para>The <c>QuotaPagedPoolUsage</c> member contains the current quota charged to the process for paged pool usage.</para>
/// <para>The <c>QuotaNonPagedPoolUsage</c> member contains the current quota charged to the process for nonpaged pool usage.</para>
/// <para>The <c>PagefileUsage</c> member contains the number of bytes of page file storage in use by the process.</para>
/// <para>The <c>PeakPagefileUsage</c> member contains the maximum number of bytes of page-file storage used by the process.</para>
/// <para>The <c>PrivatePageCount</c> member contains the number of memory pages allocated for the use of this process.</para>
/// <para>
/// You can also retrieve the <c>PeakWorkingSetSize</c>, <c>QuotaPagedPoolUsage</c>, <c>QuotaNonPagedPoolUsage</c>,
/// <c>PagefileUsage</c>, <c>PeakPagefileUsage</c>, and <c>PrivatePageCount</c> information using either the GetProcessMemoryInfo
/// function or the Win32_Process class.
/// </para>
/// <para>The other members of the structure are reserved for internal use by the operating system.</para>
/// <para>SYSTEM_THREAD_INFORMATION</para>
/// <para>
/// When the SystemInformationClass parameter is <c>SystemProcessInformation</c>, the buffer pointed to by the SystemInformation
/// parameter contains a <c>SYSTEM_PROCESS_INFORMATION</c> structure for each process. Each of these structures is immediately
/// followed in memory by one or more <c>SYSTEM_THREAD_INFORMATION</c> structures that provide info for each thread in the preceding
/// process. For more information about <c>SYSTEM_PROCESS_INFORMATION</c>, see the section about this structure in this article.
/// Each <c>SYSTEM_THREAD_INFORMATION</c> structure has the following layout:
/// </para>
/// <code>
///typedef struct _SYSTEM_THREAD_INFORMATION {
///LARGE_INTEGER Reserved1[3];
///ULONG Reserved2;
///PVOID StartAddress;
///CLIENT_ID ClientId;
///KPRIORITY Priority;
///LONG BasePriority;
///ULONG Reserved3;
///ULONG ThreadState;
///ULONG WaitReason;
///} SYSTEM_THREAD_INFORMATION;
/// </code>
/// <para>The <c>StartAddress</c> member contains the start address of the thread.</para>
/// <para>The <c>ClientId</c> member contains the ID of the thread and the process owning the thread.</para>
/// <para>The <c>Priority</c> member contains the dynamic thread priority.</para>
/// <para>The <c>BasePriority</c> member contains the base thread priority.</para>
/// <para>The <c>ThreadState</c> member contains the current thread state.</para>
/// <para>The <c>WaitReason</c> member contains the reason the thread is waiting.</para>
/// <para>The other members of the structure are reserved for internal use by the operating system.</para>
/// <para>SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION</para>
/// <para>
/// When the SystemInformationClass parameter is <c>SystemProcessorPerformanceInformation</c>, the buffer pointed to by the
/// SystemInformation parameter should be large enough to hold an array that contains as many
/// <c>SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION</c> structures as there are processors (CPUs) installed in the system. Each
/// structure has the following layout:
/// </para>
/// <code>
///typedef struct
///_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION {
///LARGE_INTEGER IdleTime;
///LARGE_INTEGER KernelTime;
///LARGE_INTEGER UserTime;
///LARGE_INTEGER Reserved1[2];
///ULONG Reserved2;
///} SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION;
/// </code>
/// <para>The <c>IdleTime</c> member contains the amount of time that the system has been idle, in 100-nanosecond intervals.</para>
/// <para>
/// The <c>KernelTime</c> member contains the amount of time that the system has spent executing in Kernel mode (including all
/// threads in all processes, on all processors), in 100-nanosecond intervals.
/// </para>
/// <para>
/// The <c>UserTime</c> member contains the amount of time that the system has spent executing in User mode (including all threads
/// in all processes, on all processors), in 100-nanosecond intervals.
/// </para>
/// <para>Use GetSystemTimesinstead to retrieve this information.</para>
/// <para>SYSTEM_QUERY_PERFORMANCE_COUNTER_INFORMATION</para>
/// <para>
/// When the SystemInformationClass parameter is <c>SystemQueryPerformanceCounterInformation</c>, the buffer pointed to by the
/// SystemInformation parameter should be large enough to hold a single <c>SYSTEM_QUERY_PERFORMANCE_COUNTER_INFORMATION</c>
/// structure having the following layout:
/// </para>
/// <code>
///typedef struct _SYSTEM_QUERY_PERFORMANCE_COUNTER_INFORMATION {
///ULONG Version;
///QUERY_PERFORMANCE_COUNTER_FLAGS Flags;
///QUERY_PERFORMANCE_COUNTER_FLAGS ValidFlags;
///} SYSTEM_QUERY_PERFORMANCE_COUNTER_INFORMATION;
/// </code>
/// <para>
/// The <c>Flags</c> and <c>ValidFlags</c> members are <c>QUERY_PERFORMANCE_COUNTER_FLAGS</c> structures having the following layout:
/// </para>
/// <code>
///typedef struct _QUERY_PERFORMANCE_COUNTER_FLAGS {
///union {
///struct {
///ULONG KernelTransition:1;
///ULONG Reserved:31;
///};
///ULONG ul;
///};
///} QUERY_PERFORMANCE_COUNTER_FLAGS;
/// </code>
/// <para>
/// The <c>ValidFlags</c> member of the <c>SYSTEM_QUERY_PERFORMANCE_COUNTER_INFORMATION</c> structure indicates which bits of the
/// <c>Flags</c> member contain valid information. If a kernel transition is required, the <c>KernelTransition</c> bit is set in
/// both <c>ValidFlags</c> and <c>Flags</c>. If a kernel transition is not required, the <c>KernelTransition</c> bit is set in
/// <c>ValidFlags</c> and clear in <c>Flags</c>.
/// </para>
/// <para>SYSTEM_REGISTRY_QUOTA_INFORMATION</para>
/// <para>
/// When the SystemInformationClass parameter is <c>SystemRegistryQuotaInformation</c>, the buffer pointed to by the
/// SystemInformation parameter should be large enough to hold a single <c>SYSTEM_REGISTRY_QUOTA_INFORMATION</c> structure having
/// the following layout:
/// </para>
/// <code>
///typedef struct _SYSTEM_REGISTRY_QUOTA_INFORMATION {
///ULONG RegistryQuotaAllowed;
///ULONG RegistryQuotaUsed;
///PVOID Reserved1;
///} SYSTEM_REGISTRY_QUOTA_INFORMATION;
/// </code>
/// <para>The <c>RegistryQuotaAllowed</c> member contains the maximum size, in bytes, that the Registry can attain on this system.</para>
/// <para>The <c>RegistryQuotaUsed</c> member contains the current size of the Registry, in bytes.</para>
/// <para>Use GetSystemRegistryQuota instead to retrieve this information.</para>
/// <para>The other member of the structure is reserved for internal use by the operating system.</para>
/// <para>SYSTEM_SPECULATION_CONTROL_INFORMATION</para>
/// <para>
/// When the SystemInformationClass parameter is <c>SystemSpeculationControlInformation</c>, the buffer pointed to by the
/// SystemInformation parameter should be large enough to hold a single <c>SYSTEM_SPECULATION_CONTROL_INFORMATION</c> structure
/// having the following layout:
/// </para>
/// <code>
///typedef struct _SYSTEM_SPECULATION_CONTROL_INFORMATION {
///struct {
///ULONG BpbEnabled:1;
///ULONG BpbDisabledSystemPolicy:1;
///ULONG BpbDisabledNoHardwareSupport:1;
///ULONG SpecCtrlEnumerated:1;
///ULONG SpecCmdEnumerated:1;
///ULONG IbrsPresent:1;
///ULONG StibpPresent:1;
///ULONG SmepPresent:1;
///ULONG Reserved:24;
///} SpeculationControlFlags;
///} SYSTEM_SPECULATION_CONTROL_INFORMATION, * PSYSTEM_SPECULATION_CONTROL_INFORMATION;
/// </code>
/// <para>The <c>BpbEnabled</c> indicates whether speculation control features are supported and enabled.</para>
/// <para>The <c>BpbDisabledSystemPolicy</c> indicates whether speculation control features are disabled due to system policy.</para>
/// <para>
/// The <c>BpbDisabledNoHardwareSupport</c> whether speculation control features are disabled due to the absence of hardware support.
/// </para>
/// <para>The <c>SpecCtrlEnumerated</c> whether the IA32_SPEC_CTRL MSR is enumerated by hardware.</para>
/// <para>The <c>SpecCmdEnumerated</c> indicates whether the IA32_SPEC_CMD MSR is enumerated by hardware.</para>
/// <para>The <c>IbrsPresent</c> indicates whether the IBRS MSR is treated as being present.</para>
/// <para>The <c>StibpPresent</c> indicates whether the STIBP MSR is present.</para>
/// <para>The <c>SmepPresent</c> indicates whether the SMEP feature is present and enabled.</para>
/// <para>The <c>Reserved</c> member of the structure is reserved for internal use by the operating system.</para>
/// <para>SYSTEM_TIMEOFDAY_INFORMATION</para>
/// <para>
/// When the SystemInformationClass parameter is <c>SystemTimeOfDayInformation</c>, the buffer pointed to by the SystemInformation
/// parameter should be large enough to hold an opaque <c>SYSTEM_TIMEOFDAY_INFORMATION</c> structure for use in generating an
/// unpredictable seed for a random number generator. For this purpose, the structure has the following layout:
/// </para>
/// <code>
///typedef struct _SYSTEM_TIMEOFDAY_INFORMATION {
///BYTE Reserved1[48];
///} SYSTEM_TIMEOFDAY_INFORMATION;
/// </code>
/// <para>Individual members of the structure are reserved for internal use by the operating system.</para>
/// <para>Use the CryptGenRandom function instead to generate cryptographically random data.</para>
/// </returns>
/// <exception cref="InvalidCastException">
/// The requested SystemInformationClass does not match the return type requested. or Reported size of object does not match query.
/// </exception>
public static T NtQuerySystemInformation<T>(SYSTEM_INFORMATION_CLASS SystemInformationClass)
{
var tType = typeof(T);
if (CorrespondingTypeAttribute.GetCorrespondingTypes(SystemInformationClass).Any() && !CorrespondingTypeAttribute.CanGet(SystemInformationClass, tType))
throw new InvalidCastException("The requested SystemInformationClass does not match the return type requested.");
var status = NtQuerySystemInformation(SystemInformationClass, SafeHGlobalHandle.Null, 0, out var len);
if (status != NTStatus.STATUS_INFO_LENGTH_MISMATCH && status != NTStatus.STATUS_BUFFER_OVERFLOW && status != NTStatus.STATUS_BUFFER_TOO_SMALL)
throw status.GetException();
var mem = new SafeHGlobalHandle(SystemInformationClass == SYSTEM_INFORMATION_CLASS.SystemProcessInformation ? (int)len * 2 : (int)len);
NtQuerySystemInformation(SystemInformationClass, mem, (uint)mem.Size, out len).ThrowIfFailed();
if (tType.IsArray)
{
var aType = tType.GetElementType();
if (aType == typeof(SYSTEM_PROCESS_INFORMATION) && SystemInformationClass == SYSTEM_INFORMATION_CLASS.SystemProcessInformation)
{
var retList = new List<SYSTEM_PROCESS_INFORMATION>();
var pi = new SYSTEM_PROCESS_INFORMATION();
var ptr = mem.DangerousGetHandle();
do
{
pi = ptr.ToStructure<SYSTEM_PROCESS_INFORMATION>();
retList.Add(pi);
ptr = ptr.Offset(pi.NextEntryOffset);
} while (pi.NextEntryOffset > 0);
return (T)(object)retList.ToArray();
}
var cnt = Math.DivRem(len, Marshal.SizeOf(aType), out var res);
if (res != 0) throw new InvalidCastException("Reported size of object does not match query.");
return (T)mem.InvokeGenericMethod("ToArray", new[] { aType }, new[] { typeof(int), typeof(int) }, new object[] { (int)cnt, 0 });
}
return mem.ToStructure<T>();
}
/// <summary>
/// <para>
/// [ <c>NtQuerySystemInformation</c> may be altered or unavailable in future versions of Windows. Applications should use the
/// alternate functions listed in this topic.]
/// </para>
/// <para>Retrieves the specified system information.</para>
/// </summary>
/// <returns>The list of results from calling NtQuerySystemInformation with SystemProcessInformation.</returns>
public static IList<Tuple<SYSTEM_PROCESS_INFORMATION, SYSTEM_THREAD_INFORMATION[]>> NtQuerySystemInformation_Process()
{
var status = NtQuerySystemInformation(SYSTEM_INFORMATION_CLASS.SystemProcessInformation, SafeHGlobalHandle.Null, 0, out var len);
if (status != NTStatus.STATUS_INFO_LENGTH_MISMATCH && status != NTStatus.STATUS_BUFFER_OVERFLOW && status != NTStatus.STATUS_BUFFER_TOO_SMALL)
throw status.GetException();
var mem = new SafeHGlobalHandle((int)len * 2);
NtQuerySystemInformation(SYSTEM_INFORMATION_CLASS.SystemProcessInformation, mem, (uint)mem.Size, out len).ThrowIfFailed();
var retList = new List<Tuple<SYSTEM_PROCESS_INFORMATION, SYSTEM_THREAD_INFORMATION[]>>();
var pi = new SYSTEM_PROCESS_INFORMATION();
var ptr = mem.DangerousGetHandle();
var pSz = Marshal.SizeOf(pi);
do
{
pi = ptr.ToStructure<SYSTEM_PROCESS_INFORMATION>();
retList.Add(new Tuple<SYSTEM_PROCESS_INFORMATION, SYSTEM_THREAD_INFORMATION[]>(pi, ptr.Offset(pSz).ToArray<SYSTEM_THREAD_INFORMATION>((int)pi.NumberOfThreads)));
ptr = ptr.Offset(pi.NextEntryOffset);
} while (pi.NextEntryOffset > 0);
return retList;
}
/// <summary>
/// Reads data from an area of memory in a specified process. The entire area to be read must be accessible or the operation fails.
/// </summary>
/// <param name="hProcess">
/// A handle to the process with memory that is being read. The handle must have PROCESS_VM_READ access to the process.
/// </param>
/// <param name="lpBaseAddress">
/// A pointer to the base address in the specified process from which to read. Before any data transfer occurs, the system verifies
/// that all data in the base address and memory of the specified size is accessible for read access, and if it is not accessible
/// the function fails.
/// </param>
/// <param name="lpBuffer">A pointer to a buffer that receives the contents from the address space of the specified process.</param>
/// <param name="nSize">The number of bytes to be read from the specified process.</param>
/// <param name="lpNumberOfBytesRead">
/// A pointer to a variable that receives the number of bytes transferred into the specified buffer. If lpNumberOfBytesRead is
/// <c>NULL</c>, the parameter is ignored.
/// </param>
/// <returns>
/// <para>Returns an NTSTATUS success or error code.</para>
/// <para>
/// The forms and significance of NTSTATUS error codes are listed in the Ntstatus.h header file available in the DDK, and are
/// described in the DDK documentation.
/// </para>
/// </returns>
[DllImport(Lib.NtDll, SetLastError = false, ExactSpelling = true)]
[PInvokeData("winternl.h")]
public static extern NTStatus NtWow64ReadVirtualMemory64([In] HPROCESS hProcess, [In] long lpBaseAddress, [Out] int lpBuffer, [In] long nSize, out long lpNumberOfBytesRead);
/// <summary>The CLIENT_ID structure contains identifiers of a process and a thread.</summary>
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct CLIENT_ID
{
/// <summary>The unique process identifier.</summary>
public IntPtr UniqueProcess;
/// <summary>The unique thread identifier.</summary>
public IntPtr UniqueThread;
}
/// <summary>
/// <para>The <c>KEY_NAME_INFORMATION</c> structure holds the name and name length of the key.</para>
/// </summary>
/// <remarks>
/// <para>
/// The ZwQueryKey routine uses the <c>KEY_NAME_INFORMATION</c> structure to contain the registry key name. When the
/// KeyInformationClass parameter of this routine is <c>KeyNameInformation</c>, the KeyInformation buffer is treated as a
/// <c>KEY_NAME_INFORMATION</c> structure. For more information about the <c>KeyNameInformation</c> enumeration value, see KEY_INFORMATION_CLASS.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/ntddk/ns-ntddk-_key_name_information typedef struct
// _KEY_NAME_INFORMATION { ULONG NameLength; WCHAR Name[1]; } KEY_NAME_INFORMATION, *PKEY_NAME_INFORMATION;
[PInvokeData("ntddk.h", MSDNShortId = "5b46e7d9-fbb0-4e55-b1f5-d9d0f1dd1f2c")]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct KEY_NAME_INFORMATION
{
/// <summary>
/// <para>The size, in bytes, of the key name string in the <c>Name</c> array.</para>
/// </summary>
public uint NameLength;
/// <summary>
/// <para>
/// An array of wide characters that contains the name of the registry key. This character string is null-terminated. Only the
/// first element in this array is included in the <c>KEY_NAME_INFORMATION</c> structure definition. The storage for the
/// remaining elements in the array immediately follows this element.
/// </para>
/// </summary>
public StrPtrUni Name;
}
/// <summary>Used by <see cref="LdrDllNotification"/>.</summary>
[PInvokeData("ntldr.h", MSDNShortId = "12202797-c80c-4fa3-9cc4-dcb1a9f01551")]
[StructLayout(LayoutKind.Sequential)]
public struct LDR_DLL_NOTIFICATION_DATA
{
/// <summary>Reserved.</summary>
public uint Flags;
/// <summary>The full path name of the DLL module.</summary>
public IntPtr FullDllName;
/// <summary>The base file name of the DLL module.</summary>
public IntPtr BaseDllName;
/// <summary>A pointer to the base address for the DLL in memory.</summary>
public IntPtr DllBase;
/// <summary>The size of the DLL image, in bytes.</summary>
public uint SizeOfImage;
}
/// <summary>
/// <para>
/// The <c>OBJECT_ATTRIBUTES</c> structure specifies attributes that can be applied to objects or object handles by routines that
/// create objects and/or return handles to objects.
/// </para>
/// </summary>
/// <remarks>
/// <para>
/// Use the InitializeObjectAttributes macro to initialize the members of the <c>OBJECT_ATTRIBUTES</c> structure. Note that
/// <c>InitializeObjectAttributes</c> initializes the <c>SecurityQualityOfService</c> member to <c>NULL</c>. If you must specify a
/// non- <c>NULL</c> value, set the <c>SecurityQualityOfService</c> member after initialization.
/// </para>
/// <para>
/// To apply the attributes contained in this structure to an object or object handle, pass a pointer to this structure to a routine
/// that accesses objects or returns object handles, such as ZwCreateFile or ZwCreateDirectoryObject.
/// </para>
/// <para>
/// All members of this structure are read-only. If a member of this structure is a pointer, the object that this member points to
/// is read-only as well. Read-only members and objects can be used to acquire relevant information but must not be modified. To set
/// the members of this structure, use the <c>InitializeObjectAttributes</c> macro.
/// </para>
/// <para>
/// Driver routines that run in a process context other than that of the system process must set the OBJ_KERNEL_HANDLE flag for the
/// <c>Attributes</c> member (by using the <c>InitializeObjectAttributes</c> macro). This restricts the use of a handle opened for
/// that object to processes running only in kernel mode. Otherwise, the handle can be accessed by the process in whose context the
/// driver is running.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/wudfwdm/ns-wudfwdm-_object_attributes typedef struct
// _OBJECT_ATTRIBUTES { ULONG Length; HANDLE RootDirectory; PUNICODE_STRING ObjectName; ULONG Attributes; PVOID SecurityDescriptor;
// PVOID SecurityQualityOfService; } OBJECT_ATTRIBUTES;
[PInvokeData("wudfwdm.h", MSDNShortId = "08f5a141-abce-4890-867c-5fe8c4239905")]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct OBJECT_ATTRIBUTES
{
/// <summary>
/// <para>
/// The number of bytes of data contained in this structure. The InitializeObjectAttributes macro sets this member to
/// <c>sizeof</c>( <c>OBJECT_ATTRIBUTES</c>).
/// </para>
/// </summary>
public uint length;
/// <summary>
/// <para>
/// Optional handle to the root object directory for the path name specified by the <c>ObjectName</c> member. If
/// <c>RootDirectory</c> is <c>NULL</c>, <c>ObjectName</c> must point to a fully qualified object name that includes the full
/// path to the target object. If <c>RootDirectory</c> is non- <c>NULL</c>, <c>ObjectName</c> specifies an object name relative
/// to the <c>RootDirectory</c> directory. The <c>RootDirectory</c> handle can refer to a file system directory or an object
/// directory in the object manager namespace.
/// </para>
/// </summary>
public IntPtr rootDirectory;
/// <summary>
/// <para>
/// Pointer to a Unicode string that contains the name of the object for which a handle is to be opened. This must either be a
/// fully qualified object name, or a relative path name to the directory specified by the <c>RootDirectory</c> member.
/// </para>
/// </summary>
public IntPtr objectName;
/// <summary>
/// <para>
/// Bitmask of flags that specify object handle attributes. This member can contain one or more of the flags in the following table.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Flag</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>OBJ_INHERIT</term>
/// <term>This handle can be inherited by child processes of the current process.</term>
/// </item>
/// <item>
/// <term>OBJ_PERMANENT</term>
/// <term>
/// This flag only applies to objects that are named within the object manager. By default, such objects are deleted when all
/// open handles to them are closed. If this flag is specified, the object is not deleted when all open handles are closed.
/// Drivers can use the ZwMakeTemporaryObject routine to make a permanent object non-permanent.
/// </term>
/// </item>
/// <item>
/// <term>OBJ_EXCLUSIVE</term>
/// <term>
/// If this flag is set and the OBJECT_ATTRIBUTES structure is passed to a routine that creates an object, the object can be
/// accessed exclusively. That is, once a process opens such a handle to the object, no other processes can open handles to this
/// object. If this flag is set and the OBJECT_ATTRIBUTES structure is passed to a routine that creates an object handle, the
/// caller is requesting exclusive access to the object for the process context that the handle was created in. This request can
/// be granted only if the OBJ_EXCLUSIVE flag was set when the object was created.
/// </term>
/// </item>
/// <item>
/// <term>OBJ_CASE_INSENSITIVE</term>
/// <term>
/// If this flag is specified, a case-insensitive comparison is used when matching the name pointed to by the ObjectName member
/// against the names of existing objects. Otherwise, object names are compared using the default system settings.
/// </term>
/// </item>
/// <item>
/// <term>OBJ_OPENIF</term>
/// <term>
/// If this flag is specified, by using the object handle, to a routine that creates objects and if that object already exists,
/// the routine should open that object. Otherwise, the routine creating the object returns an NTSTATUS code of STATUS_OBJECT_NAME_COLLISION.
/// </term>
/// </item>
/// <item>
/// <term>OBJ_OPENLINK</term>
/// <term>
/// If an object handle, with this flag set, is passed to a routine that opens objects and if the object is a symbolic link
/// object, the routine should open the symbolic link object itself, rather than the object that the symbolic link refers to
/// (which is the default behavior).
/// </term>
/// </item>
/// <item>
/// <term>OBJ_KERNEL_HANDLE</term>
/// <term>The handle is created in system process context and can only be accessed from kernel mode.</term>
/// </item>
/// <item>
/// <term>OBJ_FORCE_ACCESS_CHECK</term>
/// <term>
/// The routine that opens the handle should enforce all access checks for the object, even if the handle is being opened in
/// kernel mode.
/// </term>
/// </item>
/// <item>
/// <term>OBJ_VALID_ATTRIBUTES</term>
/// <term>Reserved.</term>
/// </item>
/// </list>
/// </summary>
public uint attributes;
/// <summary>
/// <para>
/// Specifies a security descriptor (SECURITY_DESCRIPTOR) for the object when the object is created. If this member is
/// <c>NULL</c>, the object will receive default security settings.
/// </para>
/// </summary>
public IntPtr securityDescriptor;
/// <summary>
/// <para>
/// Optional quality of service to be applied to the object when it is created. Used to indicate the security impersonation
/// level and context tracking mode (dynamic or static). Currently, the InitializeObjectAttributes macro sets this member to <c>NULL</c>.
/// </para>
/// </summary>
public IntPtr securityQualityOfService;
}
/// <summary>Provides a <see cref="SafeHandle"/> to an enlistment that releases its handle at disposal using NTClose.</summary>
public class SafeEnlistmentHandle : SafeNtHandle
{
/// <summary>Initializes a new instance of the <see cref="SafeResourceManagerHandle"/> class and assigns an existing handle.</summary>
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
/// <param name="ownsHandle">
/// <see langword="true"/> to reliably release the handle during the finalization phase; otherwise, <see langword="false"/> (not recommended).
/// </param>
public SafeEnlistmentHandle(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
/// <summary>Initializes a new instance of the <see cref="SafeResourceManagerHandle"/> class.</summary>
private SafeEnlistmentHandle() : base() { }
}
/// <summary>Provides a <see cref="SafeHandle"/> to an object that releases a created handle at disposal using NtClose.</summary>
public abstract class SafeNtHandle : SafeHANDLE
{
/// <summary>Initializes a new instance of the <see cref="SafeNtHandle"/> class and assigns an existing handle.</summary>
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
/// <param name="ownsHandle">
/// <see langword="true"/> to reliably release the handle during the finalization phase; otherwise, <see langword="false"/> (not recommended).
/// </param>
public SafeNtHandle(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
/// <summary>Initializes a new instance of the <see cref="SafeNtHandle"/> class.</summary>
protected SafeNtHandle() : base() { }
#pragma warning disable CS0612 // Type or member is obsolete
/// <inheritdoc/>
protected override bool InternalReleaseHandle() => NtClose(handle).Succeeded;
#pragma warning restore CS0612 // Type or member is obsolete
}
/// <summary>Provides a <see cref="SafeHandle"/> to a resource manager that releases its handle at disposal using NTClose.</summary>
public class SafeResourceManagerHandle : SafeNtHandle
{
/// <summary>Initializes a new instance of the <see cref="SafeResourceManagerHandle"/> class and assigns an existing handle.</summary>
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
/// <param name="ownsHandle">
/// <see langword="true"/> to reliably release the handle during the finalization phase; otherwise, <see langword="false"/> (not recommended).
/// </param>
public SafeResourceManagerHandle(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
/// <summary>Initializes a new instance of the <see cref="SafeResourceManagerHandle"/> class.</summary>
private SafeResourceManagerHandle() : base() { }
}
/// <summary>Provides a <see cref="SafeHandle"/> to a section that releases its handle at disposal using NTClose.</summary>
public class SafeSectionHandle : SafeNtHandle
{
/// <summary>Initializes a new instance of the <see cref="SafeSectionHandle"/> class and assigns an existing handle.</summary>
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
/// <param name="ownsHandle">
/// <see langword="true"/> to reliably release the handle during the finalization phase; otherwise, <see langword="false"/> (not recommended).
/// </param>
public SafeSectionHandle(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
/// <summary>Initializes a new instance of the <see cref="SafeSectionHandle"/> class.</summary>
private SafeSectionHandle() : base() { }
}
/// <summary>Provides a <see cref="SafeHandle"/> to a transaction that releases its handle at disposal using NTClose.</summary>
public class SafeTransactionHandle : SafeNtHandle
{
/// <summary>Initializes a new instance of the <see cref="SafeTransactionHandle"/> class and assigns an existing handle.</summary>
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
/// <param name="ownsHandle">
/// <see langword="true"/> to reliably release the handle during the finalization phase; otherwise, <see langword="false"/> (not recommended).
/// </param>
public SafeTransactionHandle(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
/// <summary>Initializes a new instance of the <see cref="SafeTransactionHandle"/> class.</summary>
private SafeTransactionHandle() : base() { }
}
/// <summary>Provides a <see cref="SafeHandle"/> to a transaction manager that releases its handle at disposal using NTClose.</summary>
public class SafeTransactionManagerHandle : SafeNtHandle
{
/// <summary>Initializes a new instance of the <see cref="SafeTransactionManagerHandle"/> class and assigns an existing handle.</summary>
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
/// <param name="ownsHandle">
/// <see langword="true"/> to reliably release the handle during the finalization phase; otherwise, <see langword="false"/> (not recommended).
/// </param>
public SafeTransactionManagerHandle(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
/// <summary>Initializes a new instance of the <see cref="SafeTransactionManagerHandle"/> class.</summary>
private SafeTransactionManagerHandle() : base() { }
}
/*
NtDeviceIoControlFile
NtDuplicateToken
NtEnumerateTransactionObject
NtFlushBuffersFileEx
NtFreeVirtualMemory
NtFsControlFile
NtGetCurrentProcessorNumber
NtGetNotificationResourceManager
NtLockFile
NtNotifyChangeMultipleKeys
NtOpenDirectoryObject
NtOpenEnlistment
NtOpenFile
NtOpenProcess
NtOpenProcessTokenEx
NtOpenResourceManager
NtOpenSymbolicLinkObject
NtOpenThread
NtOpenThreadTokenEx
NtOpenTransaction
NtOpenTransactionManager
NtPowerInformation
NtPrepareComplete
NtPrepareEnlistment
NtPrePrepareComplete
NtPrePrepareEnlistment
NtProtectVirtualMemory
NtQueryAttributesFile
NtQueryDirectoryFile
NtQueryInformationEnlistment
NtQueryInformationFile
NtQueryInformationProcess
NtQueryInformationResourceManager
NtQueryInformationThread
NtQueryInformationToken
NtQueryInformationTransaction
NtQueryInformationTransactionManager
NtQueryMultipleValueKey
NtQueryObject
NtQueryPerformanceCounter
NtQueryQuotaInformationFile
NtQuerySecurityObject
NtQuerySymbolicLinkObject
NtQuerySystemTime
NtQueryVirtualMemory
NtQueryVolumeInformationFile
NtReadFile
NtReadOnlyEnlistment
NtRecoverEnlistment
NtRecoverResourceManager
NtRecoverTransactionManager
NtRenameKey
NtRenameTransactionManager
NtRollbackComplete
NtRollbackEnlistment
NtRollbackTransaction
NtRollforwardTransactionManager
NtSetInformationEnlistment
NtSetInformationFile
NtSetInformationKey
NtSetInformationResourceManager
NtSetInformationThread
NtSetInformationToken
NtSetInformationTransaction
NtSetInformationTransactionManager
NtSetQuotaInformationFile
NtSetSecurityObject
NtSinglePhaseReject
NtUnlockFile
NtUnmapViewOfSection
NtWaitForSingleObject
NtWriteFile
RtlAbsoluteToSelfRelativeSD
RtlAddAccessAllowedAce
RtlAddAccessAllowedAceEx
RtlAddAce
RtlAddFunctionTable
RtlAddGrowableFunctionTable
RtlAllocateAndInitializeSid
RtlAllocateHeap
RtlAppendStringToString
RtlAppendUnicodeToString
RtlAreBitsClear
RtlAreBitsSet
RtlCaptureContext
RtlCaptureStackBackTrace
RtlCharToInteger
RtlCheckRegistryKey
RtlClearBits
RtlCmEncodeMemIoResource
RtlCompareMemory
RtlCompareMemoryUlong
RtlCompareString
RtlCompressBuffer
RtlCopyLuid
RtlCopyMemoryNonTemporal
RtlCopySid
RtlCopyString
RtlCreateAcl
RtlCreateHeap
RtlCreateRegistryKey
RtlCreateSecurityDescriptor
RtlCreateSystemVolumeInformationFolder
RtlCustomCPToUnicodeN
RtlDecompressBuffer
RtlDecompressBufferEx
RtlDecompressFragment
RtlDelete
RtlDeleteAce
RtlDeleteElementGenericTable
RtlDeleteElementGenericTableAvl
RtlDeleteFunctionTable
RtlDeleteGrowableFunctionTable
RtlDeleteNoSplay
RtlDeleteRegistryValue
RtlDestroyHeap
RtlDrainNonVolatileFlush
RtlEnumerateGenericTable
RtlEnumerateGenericTableAvl
RtlEnumerateGenericTableLikeADirectory
RtlEnumerateGenericTableWithoutSplaying
RtlEnumerateGenericTableWithoutSplayingAvl
RtlEqualPrefixSid
RtlEqualSid
RtlEthernetAddressToStringA
RtlEthernetAddressToStringW
RtlEthernetStringToAddressA
RtlEthernetStringToAddressW
RtlFindClearBits
RtlFindClearBitsAndSet
RtlFindClearRuns
RtlFindLastBackwardRunClear
RtlFindLeastSignificantBit
RtlFindLongestRunClear
RtlFindMostSignificantBit
RtlFindNextForwardRunClear
RtlFindSetBits
RtlFindSetBitsAndClear
RtlFirstEntrySList
RtlFlushNonVolatileMemory
RtlFlushNonVolatileMemoryRanges
RtlFreeAnsiString
RtlFreeHeap
RtlFreeNonVolatileToken
RtlFreeOemString
RtlGenerate8dot3Name
RtlGetAce
RtlGetCompressionWorkSpaceSize
RtlGetDaclSecurityDescriptor
RtlGetElementGenericTable
RtlGetElementGenericTableAvl
RtlGetEnabledExtendedFeatures
RtlGetFunctionTableListHead
RtlGetGroupSecurityDescriptor
RtlGetNonVolatileToken
RtlGetOwnerSecurityDescriptor
RtlGetSaclSecurityDescriptor
RtlGetUnloadEventTrace
RtlGetUnloadEventTraceEx
RtlGetVersion
RtlGrowFunctionTable
RtlGUIDFromString
RtlInitAnsiString
RtlInitCodePageTable
RtlInitializeBitMap
RtlInitializeGenericTable
RtlInitializeGenericTableAvl
RtlInitializeSid
RtlInitializeSidEx
RtlInitializeSListHead
RtlInitString
RtlInitStringEx
RtlInsertElementGenericTable
RtlInsertElementGenericTableAvl
RtlInsertElementGenericTableFullAvl
RtlInstallFunctionTableCallback
RtlInterlockedFlushSList
RtlInterlockedPushEntrySList
RtlIoDecodeMemIoResource
RtlIoEncodeMemIoResource
RtlIpv4AddressToStringA
RtlIpv4AddressToStringExW
RtlIpv4StringToAddressA
RtlIpv4StringToAddressExA
RtlIpv4StringToAddressExW
RtlIpv4StringToAddressW
RtlIpv6AddressToStringA
RtlIpv6AddressToStringExW
RtlIpv6AddressToStringW
RtlIpv6StringToAddressA
RtlIpv6StringToAddressExW
RtlIpv6StringToAddressW
RtlIsGenericTableEmpty
RtlIsGenericTableEmptyAvl
RtlIsNameInExpression
RtlIsNameLegalDOS8Dot3
RtlIsValidLocaleName
RtlLengthSecurityDescriptor
RtlLengthSid
RtlLocalTimeToSystemTime
RtlLookupElementGenericTable
RtlLookupElementGenericTableAvl
RtlLookupElementGenericTableFullAvl
RtlLookupFirstMatchingElementGenericTableAvl
RtlLookupFunctionEntry
RtlMapGenericMask
RtlMoveMemory
RtlMultiByteToUnicodeN
RtlMultiByteToUnicodeSize
RtlNtStatusToDosError
RtlNumberGenericTableElements
RtlNumberGenericTableElementsAvl
RtlNumberOfClearBits
RtlNumberOfSetBits
RtlNumberOfSetBitsUlongPtr
RtlOemToUnicodeN
RtlPcToFileHeader
RtlQueryDepthSList
RtlQueryRegistryValues
RtlRaiseException
RtlRandom
RtlRandomEx
RtlRealPredecessor
RtlRealSuccessor
RtlRestoreContext
RtlRunOnceBeginInitialize
RtlRunOnceComplete
RtlRunOnceExecuteOnce
RtlRunOnceInitialize
RtlSecondsSince1970ToTime
RtlSecondsSince1980ToTime
RtlSelfRelativeToAbsoluteSD
RtlSetAllBits
RtlSetBits
RtlSetDaclSecurityDescriptor
RtlSetGroupSecurityDescriptor
RtlSetOwnerSecurityDescriptor
RtlSplay
RtlStringFromGUID
RtlSubAuthorityCountSid
RtlSubAuthoritySid
RtlSubtreePredecessor
RtlSubtreeSuccessor
RtlTimeFieldsToTime
RtlTimeToSecondsSince1970
RtlTimeToSecondsSince1980
RtlTimeToTimeFields
RtlUnicodeToCustomCPN
RtlUnicodeToMultiByteN
RtlUnicodeToMultiByteSize
RtlUnicodeToOemN
RtlUnicodeToUTF8N
RtlUniform
RtlUnwind
RtlUpcaseUnicodeChar
RtlUpcaseUnicodeToCustomCPN
RtlUpcaseUnicodeToMultiByteN
RtlUpcaseUnicodeToOemN
RtlUpperChar
RtlUpperString
RtlUTF8ToUnicodeN
RtlValidRelativeSecurityDescriptor
RtlVerifyVersionInfo
RtlVirtualUnwind
RtlWriteNonVolatileMemory
RtlWriteRegistryValue
vDbgPrintEx
vDbgPrintExWithPrefix
VerSetConditionMask
ZwAllocateLocallyUniqueId
ZwAllocateVirtualMemory
ZwClose
ZwCommitComplete
ZwCommitEnlistment
ZwCommitTransaction
ZwCreateDirectoryObject
ZwCreateEnlistment
ZwCreateEvent
ZwCreateFile
ZwCreateKey
ZwCreateKeyTransacted
ZwCreateResourceManager
ZwCreateSection
ZwCreateTransaction
ZwCreateTransactionManager
ZwDeleteFile
ZwDeleteKey
ZwDeleteValueKey
ZwDeviceIoControlFile
ZwDuplicateObject
ZwDuplicateToken
ZwEnumerateKey
ZwEnumerateTransactionObject
ZwEnumerateValueKey
ZwFlushBuffersFileEx
ZwFlushKey
ZwFlushVirtualMemory
ZwFreeVirtualMemory
ZwFsControlFile
ZwGetNotificationResourceManager
ZwLoadDriver
ZwLockFile
ZwMakeTemporaryObject
ZwMapViewOfSection
ZwNotifyChangeKey
ZwOpenDirectoryObject
ZwOpenEnlistment
ZwOpenEvent
ZwOpenFile
ZwOpenKey
ZwOpenKeyEx
ZwOpenKeyTransacted
ZwOpenKeyTransactedEx
ZwOpenProcess
ZwOpenProcessTokenEx
ZwOpenResourceManager
ZwOpenSection
ZwOpenSymbolicLinkObject
ZwOpenThreadTokenEx
ZwOpenTransaction
ZwOpenTransactionManager
ZwPowerInformation
ZwPrepareComplete
ZwPrepareEnlistment
ZwPrePrepareComplete
ZwPrePrepareEnlistment
ZwQueryDirectoryFile
ZwQueryEaFile
ZwQueryFullAttributesFile
ZwQueryInformationEnlistment
ZwQueryInformationFile
ZwQueryInformationProcess
ZwQueryInformationResourceManager
ZwQueryInformationToken
ZwQueryInformationTransaction
ZwQueryInformationTransactionManager
ZwQueryKey
ZwQueryObject
ZwQueryQuotaInformationFile
ZwQuerySecurityObject
ZwQuerySymbolicLinkObject
ZwQuerySystemInformation
ZwQuerySystemInformationEx
ZwQueryValueKey
ZwQueryVirtualMemory
ZwQueryVolumeInformationFile
ZwReadFile
ZwReadOnlyEnlistment
ZwRecoverEnlistment
ZwRecoverResourceManager
ZwRecoverTransactionManager
ZwRollbackComplete
ZwRollbackEnlistment
ZwRollbackTransaction
ZwRollforwardTransactionManager
ZwSetEaFile
ZwSetEvent
ZwSetInformationEnlistment
ZwSetInformationFile
ZwSetInformationResourceManager
ZwSetInformationThread
ZwSetInformationToken
ZwSetInformationTransaction
ZwSetInformationVirtualMemory
ZwSetQuotaInformationFile
ZwSetSecurityObject
ZwSetValueKey
ZwSetVolumeInformationFile
ZwSinglePhaseReject
ZwSuspendProcess
ZwTerminateProcess
ZwUnloadDriver
ZwUnlockFile
ZwUnmapViewOfSection
ZwUnmapViewOfSectionEx
ZwWaitForSingleObject
ZwWriteFile
*/
}
}