using System; using System.Linq; using System.Runtime.InteropServices; using Vanara.InteropServices; using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME; namespace Vanara.PInvoke { /// Platform invokable enumerated types, constants and functions from ntdll.h public static partial class NtDll { #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member /// [Flags] public enum PROCESS_CREATE_FLAGS : uint { /// PROCESS_CREATE_FLAGS_BREAKAWAY = 0x00000001, /// PROCESS_CREATE_FLAGS_NO_DEBUG_INHERIT = 0x00000002, /// PROCESS_CREATE_FLAGS_INHERIT_HANDLES = 0x00000004, /// PROCESS_CREATE_FLAGS_OVERRIDE_ADDRESS_SPACE = 0x00000008, /// PROCESS_CREATE_FLAGS_LARGE_PAGES = 0x00000010, } /// The type of process information to be retrieved. [PInvokeData("winternl.h", MSDNShortId = "0eae7899-c40b-4a5f-9e9c-adae021885e7")] // Undocumented values pulled from ProcessHacker source. public enum PROCESSINFOCLASS { /// /// Retrieves a pointer to a PEB structure that can be used to determine whether the specified process is being debugged, and a /// unique value used by the system to identify the specified process. /// Use the CheckRemoteDebuggerPresent and GetProcessId functions to obtain this information. /// [CorrespondingType(typeof(PROCESS_BASIC_INFORMATION), CorrespondingAction.Get)] [CorrespondingType(typeof(PROCESS_BASIC_INFORMATION_WOW64), CorrespondingAction.Get)] ProcessBasicInformation = 0, ProcessQuotaLimits, // qs: QUOTA_LIMITS, QUOTA_LIMITS_EX ProcessIoCounters, // q: IO_COUNTERS ProcessVmCounters, // q: VM_COUNTERS, VM_COUNTERS_EX, VM_COUNTERS_EX2 [CorrespondingType(typeof(KERNEL_USER_TIMES), CorrespondingAction.Get)] ProcessTimes, // q: KERNEL_USER_TIMES ProcessBasePriority, // s: KPRIORITY ProcessRaisePriority, // s: ULONG /// /// Retrieves a DWORD_PTR value that is the port number of the debugger for the process. A nonzero value indicates that the /// process is being run under the control of a ring 3 debugger. /// Use the CheckRemoteDebuggerPresent or IsDebuggerPresent function. /// [CorrespondingType(typeof(IntPtr), CorrespondingAction.Get)] ProcessDebugPort = 7, ProcessExceptionPort, // s: PROCESS_EXCEPTION_PORT ProcessAccessToken, // s: PROCESS_ACCESS_TOKEN ProcessLdtInformation, // qs: PROCESS_LDT_INFORMATION // 10 ProcessLdtSize, // s: PROCESS_LDT_SIZE ProcessDefaultHardErrorMode, // qs: ULONG ProcessIoPortHandlers, // (kernel-mode only) // PROCESS_IO_PORT_HANDLER_INFORMATION ProcessPooledUsageAndLimits, // q: POOLED_USAGE_AND_LIMITS ProcessWorkingSetWatch, // q: PROCESS_WS_WATCH_INFORMATION[]; s: void ProcessUserModeIOPL, // qs: ULONG (requires SeTcbPrivilege) ProcessEnableAlignmentFaultFixup, // s: BOOLEAN ProcessPriorityClass, // qs: PROCESS_PRIORITY_CLASS ProcessWx86Information, // qs: ULONG (requires SeTcbPrivilege) (VdmAllowed) ProcessHandleCount, // q: ULONG, PROCESS_HANDLE_INFORMATION // 20 ProcessAffinityMask, // s: KAFFINITY ProcessPriorityBoost, // qs: ULONG ProcessDeviceMap, // qs: PROCESS_DEVICEMAP_INFORMATION, PROCESS_DEVICEMAP_INFORMATION_EX ProcessSessionInformation, // q: PROCESS_SESSION_INFORMATION ProcessForegroundInformation, // s: PROCESS_FOREGROUND_BACKGROUND /// /// Determines whether the process is running in the WOW64 environment (WOW64 is the x86 emulator that allows Win32-based /// applications to run on 64-bit Windows). /// Use the IsWow64Process2 function to obtain this information. /// [CorrespondingType(typeof(BOOL), CorrespondingAction.Get)] ProcessWow64Information = 26, /// /// Retrieves a UNICODE_STRING value containing the name of the image file for the process. /// Use the QueryFullProcessImageName or GetProcessImageFileName function to obtain this information. /// [CorrespondingType(typeof(UNICODE_STRING), CorrespondingAction.Get)] [CorrespondingType(typeof(UNICODE_STRING_WOW64), CorrespondingAction.Get)] ProcessImageFileName = 27, ProcessLUIDDeviceMapsEnabled, // q: ULONG /// /// Retrieves a ULONG value indicating whether the process is considered critical. /// /// Note This value can be used starting in Windows XP with SP3. Starting in Windows 8.1, IsProcessCritical should be used instead. /// /// [CorrespondingType(typeof(BOOL), CorrespondingAction.GetSet)] ProcessBreakOnTermination = 29, ProcessDebugObjectHandle, // q: HANDLE // 30 ProcessDebugFlags, // qs: ULONG ProcessHandleTracing, // q: PROCESS_HANDLE_TRACING_QUERY; s: size 0 disables, otherwise enables ProcessIoPriority, // qs: IO_PRIORITY_HINT ProcessExecuteFlags, // qs: ULONG ProcessResourceManagement, // ProcessTlsInformation // PROCESS_TLS_INFORMATION ProcessCookie, // q: ULONG ProcessImageInformation, // q: SECTION_IMAGE_INFORMATION ProcessCycleTime, // q: PROCESS_CYCLE_TIME_INFORMATION // since VISTA ProcessPagePriority, // q: PAGE_PRIORITY_INFORMATION ProcessInstrumentationCallback, // qs: PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION // 40 ProcessThreadStackAllocation, // s: PROCESS_STACK_ALLOCATION_INFORMATION, PROCESS_STACK_ALLOCATION_INFORMATION_EX ProcessWorkingSetWatchEx, // q: PROCESS_WS_WATCH_INFORMATION_EX[] ProcessImageFileNameWin32, // q: UNICODE_STRING ProcessImageFileMapping, // q: HANDLE (input) ProcessAffinityUpdateMode, // qs: PROCESS_AFFINITY_UPDATE_MODE ProcessMemoryAllocationMode, // qs: PROCESS_MEMORY_ALLOCATION_MODE ProcessGroupInformation, // q: USHORT[] ProcessTokenVirtualizationEnabled, // s: ULONG ProcessConsoleHostProcess, // q: ULONG_PTR // ProcessOwnerInformation ProcessWindowInformation, // q: PROCESS_WINDOW_INFORMATION // 50 ProcessHandleInformation, // q: PROCESS_HANDLE_SNAPSHOT_INFORMATION // since WIN8 ProcessMitigationPolicy, // s: PROCESS_MITIGATION_POLICY_INFORMATION ProcessDynamicFunctionTableInformation, ProcessHandleCheckingMode, // qs: ULONG; s: 0 disables, otherwise enables ProcessKeepAliveCount, // q: PROCESS_KEEPALIVE_COUNT_INFORMATION ProcessRevokeFileHandles, // s: PROCESS_REVOKE_FILE_HANDLES_INFORMATION ProcessWorkingSetControl, // s: PROCESS_WORKING_SET_CONTROL ProcessHandleTable, // q: ULONG[] // since WINBLUE ProcessCheckStackExtentsMode, ProcessCommandLineInformation, // q: UNICODE_STRING // 60 ProcessProtectionInformation, // q: PS_PROTECTION ProcessMemoryExhaustion, // PROCESS_MEMORY_EXHAUSTION_INFO // since THRESHOLD ProcessFaultInformation, // PROCESS_FAULT_INFORMATION ProcessTelemetryIdInformation, // PROCESS_TELEMETRY_ID_INFORMATION ProcessCommitReleaseInformation, // PROCESS_COMMIT_RELEASE_INFORMATION ProcessDefaultCpuSetsInformation, ProcessAllowedCpuSetsInformation, ProcessSubsystemProcess, ProcessJobMemoryInformation, // PROCESS_JOB_MEMORY_INFO ProcessInPrivate, // since THRESHOLD2 // 70 ProcessRaiseUMExceptionOnInvalidHandleClose, // qs: ULONG; s: 0 disables, otherwise enables ProcessIumChallengeResponse, ProcessChildProcessInformation, // PROCESS_CHILD_PROCESS_INFORMATION ProcessHighGraphicsPriorityInformation, /// /// Retrieves a SUBSYSTEM_INFORMATION_TYPE value indicating the subsystem type of the process. The buffer pointed to by the /// ProcessInformation parameter should be large enough to hold a single SUBSYSTEM_INFORMATION_TYPE enumeration. /// [CorrespondingType(typeof(SUBSYSTEM_INFORMATION_TYPE), CorrespondingAction.Get)] ProcessSubsystemInformation = 75, ProcessEnergyValues, // PROCESS_ENERGY_VALUES, PROCESS_EXTENDED_ENERGY_VALUES ProcessActivityThrottleState, // PROCESS_ACTIVITY_THROTTLE_STATE ProcessActivityThrottlePolicy, // PROCESS_ACTIVITY_THROTTLE_POLICY ProcessWin32kSyscallFilterInformation, ProcessDisableSystemAllowedCpuSets, // 80 ProcessWakeInformation, // PROCESS_WAKE_INFORMATION ProcessEnergyTrackingState, // PROCESS_ENERGY_TRACKING_STATE ProcessManageWritesToExecutableMemory, // MANAGE_WRITES_TO_EXECUTABLE_MEMORY // since REDSTONE3 ProcessCaptureTrustletLiveDump, ProcessTelemetryCoverage, ProcessEnclaveInformation, ProcessEnableReadWriteVmLogging, // PROCESS_READWRITEVM_LOGGING_INFORMATION ProcessUptimeInformation, // PROCESS_UPTIME_INFORMATION ProcessImageSection, // q: HANDLE ProcessDebugAuthInformation, // since REDSTONE4 // 90 ProcessSystemResourceManagement, // PROCESS_SYSTEM_RESOURCE_MANAGEMENT ProcessSequenceNumber, // q: ULONGLONG ProcessLoaderDetour, // since REDSTONE5 ProcessSecurityDomainInformation, // PROCESS_SECURITY_DOMAIN_INFORMATION ProcessCombineSecurityDomainsInformation, // PROCESS_COMBINE_SECURITY_DOMAINS_INFORMATION ProcessEnableLogging, // PROCESS_LOGGING_INFORMATION ProcessLeapSecondInformation, // PROCESS_LEAP_SECOND_INFORMATION ProcessFiberShadowStackAllocation, // PROCESS_FIBER_SHADOW_STACK_ALLOCATION_INFORMATION // since 19H1 ProcessFreeFiberShadowStackAllocation, // PROCESS_FREE_FIBER_SHADOW_STACK_ALLOCATION_INFORMATION ProcessAltSystemCallInformation, // qs: BOOLEAN (kernel-mode only) // since 20H1 // 100 ProcessDynamicEHContinuationTargets, // PROCESS_DYNAMIC_EH_CONTINUATION_TARGETS_INFORMATION } #pragma warning restore CS1591 // Missing XML comment for publicly visible type or member /// /// Indicates the type of subsystem for a process or thread. This enumeration is used in NtQueryInformationProcess and /// NtQueryInformationThread calls. /// // https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntddk/ne-ntddk-_subsystem_information_type typedef enum // _SUBSYSTEM_INFORMATION_TYPE { SubsystemInformationTypeWin32, SubsystemInformationTypeWSL, MaxSubsystemInformationType } // SUBSYSTEM_INFORMATION_TYPE, *PSUBSYSTEM_INFORMATION_TYPE; [PInvokeData("ntddk.h", MSDNShortId = "B1E334BF-AAB3-410D-8D10-A750E8459E42")] public enum SUBSYSTEM_INFORMATION_TYPE { /// The subsystem type for the process or thread is Win32. SubsystemInformationTypeWin32, /// /// The subsystem type for the process or thread is Windows Subsystem for Linux (WSL). For this process, these members of the /// PS_CREATE_NOTIFY_INFO structure are set as follows: The preceding member values may be NULL. /// SubsystemInformationTypeWSL, /// Reserved. MaxSubsystemInformationType, } /// Creates a process. This function is UNDOCUMENTED. /// The process handle. /// The desired access. /// The object attributes. /// The parent process. /// if set to , inherits the object table. /// The section handle. /// The debug port. /// The exception port. /// /// The function returns an NTSTATUS success or error code. /// /// 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 under Kernel-Mode Driver Architecture / Design Guide / Driver Programming Techniques / /// Logging Errors. /// /// [DllImport(Lib.NtDll, SetLastError = false, ExactSpelling = true)] public static extern NTStatus NtCreateProcess(out HPROCESS ProcessHandle, [In] ACCESS_MASK DesiredAccess, in OBJECT_ATTRIBUTES ObjectAttributes, [In] HPROCESS ParentProcess, [In, MarshalAs(UnmanagedType.U1)] bool InheritObjectTable, [In, Optional] IntPtr SectionHandle, [In, Optional] IntPtr DebugPort, [In, Optional] IntPtr ExceptionPort); /// Creates a process. This function is UNDOCUMENTED. /// The process handle. /// The desired access. /// The object attributes. /// The parent process. /// if set to , inherits the object table. /// The section handle. /// The debug port. /// The exception port. /// /// The function returns an NTSTATUS success or error code. /// /// 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 under Kernel-Mode Driver Architecture / Design Guide / Driver Programming Techniques / /// Logging Errors. /// /// [DllImport(Lib.NtDll, SetLastError = false, ExactSpelling = true)] public static extern NTStatus NtCreateProcess(out HPROCESS ProcessHandle, [In] ACCESS_MASK DesiredAccess, [In, Optional] IntPtr ObjectAttributes, [In] HPROCESS ParentProcess, [In, MarshalAs(UnmanagedType.U1)] bool InheritObjectTable, [In, Optional] IntPtr SectionHandle, [In, Optional] IntPtr DebugPort, [In, Optional] IntPtr ExceptionPort); /// Creates a process. This function is UNDOCUMENTED. /// The process handle. /// The desired access. /// The object attributes. /// The parent process. /// The flags. /// The section handle. /// The debug port. /// The exception port. /// The job member level. /// /// The function returns an NTSTATUS success or error code. /// /// 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 under Kernel-Mode Driver Architecture / Design Guide / Driver Programming Techniques / /// Logging Errors. /// /// [DllImport(Lib.NtDll, SetLastError = false, ExactSpelling = true)] public static extern NTStatus NtCreateProcessEx(out HPROCESS ProcessHandle, [In] ACCESS_MASK DesiredAccess, in OBJECT_ATTRIBUTES ObjectAttributes, [In] HPROCESS ParentProcess, [In] PROCESS_CREATE_FLAGS Flags, [In, Optional] IntPtr SectionHandle, [In, Optional] IntPtr DebugPort, [In, Optional] IntPtr ExceptionPort, uint JobMemberLevel); /// Creates a process. This function is UNDOCUMENTED. /// The process handle. /// The desired access. /// The object attributes. /// The parent process. /// The flags. /// The section handle. /// The debug port. /// The exception port. /// The job member level. /// /// The function returns an NTSTATUS success or error code. /// /// 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 under Kernel-Mode Driver Architecture / Design Guide / Driver Programming Techniques / /// Logging Errors. /// /// [DllImport(Lib.NtDll, SetLastError = false, ExactSpelling = true)] public static extern NTStatus NtCreateProcessEx(out HPROCESS ProcessHandle, [In] ACCESS_MASK DesiredAccess, [In, Optional] IntPtr ObjectAttributes, [In] HPROCESS ParentProcess, [In] PROCESS_CREATE_FLAGS Flags, [In, Optional] IntPtr SectionHandle, [In, Optional] IntPtr DebugPort, [In, Optional] IntPtr ExceptionPort, uint JobMemberLevel); /// /// /// [ NtQueryInformationProcess may be altered or unavailable in future versions of Windows. Applications should use the /// alternate functions listed in this topic.] /// /// Retrieves information about the specified process. /// /// A handle to the process for which information is to be retrieved. /// /// /// The type of process information to be retrieved. This parameter can be one of the following values from the /// PROCESSINFOCLASS enumeration. /// /// /// /// Value /// Meaning /// /// /// ProcessBasicInformation
0
/// /// Retrieves a pointer to a PEB structure that can be used to determine whether the specified process is being debugged, and a /// unique value used by the system to identify the specified process. Use the CheckRemoteDebuggerPresent and GetProcessId functions /// to obtain this information. /// ///
/// /// ProcessDebugPort
7
/// /// Retrieves a DWORD_PTR value that is the port number of the debugger for the process. A nonzero value indicates that the process /// is being run under the control of a ring 3 debugger. Use the CheckRemoteDebuggerPresent or IsDebuggerPresent function. /// ///
/// /// ProcessWow64Information
26
/// /// Determines whether the process is running in the WOW64 environment (WOW64 is the x86 emulator that allows Win32-based /// applications to run on 64-bit Windows). Use the IsWow64Process2 function to obtain this information. /// ///
/// /// ProcessImageFileName
27
/// /// Retrieves a UNICODE_STRING value containing the name of the image file for the process. Use the QueryFullProcessImageName or /// GetProcessImageFileName function to obtain this information. /// ///
/// /// ProcessBreakOnTermination
29
/// Retrieves a ULONG value indicating whether the process is considered critical. ///
/// /// ProcessSubsystemInformation
75
/// /// Retrieves a SUBSYSTEM_INFORMATION_TYPE value indicating the subsystem type of the process. The buffer pointed to by the /// ProcessInformation parameter should be large enough to hold a single SUBSYSTEM_INFORMATION_TYPE enumeration. /// ///
///
/// /// /// /// A pointer to a buffer supplied by the calling application into which the function writes the requested information. The size of /// the information written varies depending on the data type of the ProcessInformationClass parameter: /// /// PROCESS_BASIC_INFORMATION /// /// When the ProcessInformationClass parameter is ProcessBasicInformation, the buffer pointed to by the ProcessInformation /// parameter should be large enough to hold a single PROCESS_BASIC_INFORMATION structure having the following layout: /// /// /// /// The UniqueProcessId member points to the system's unique identifier for this process. Use the GetProcessId function to /// retrieve this information. /// /// The PebBaseAddress member points to a PEB structure. /// The other members of this structure are reserved for internal use by the operating system. /// ULONG_PTR /// /// When the ProcessInformationClass parameter is ProcessWow64Information, the buffer pointed to by the ProcessInformation /// parameter should be large enough to hold a ULONG_PTR. If this value is nonzero, the process is running in a WOW64 /// environment; otherwise, if the value is equal to zero, the process is not running in a WOW64 environment. /// /// Use the IsWow64Process2 function to determine whether a process is running in the WOW64 environment. /// UNICODE_STRING /// /// When the ProcessInformationClass parameter is ProcessImageFileName, the buffer pointed to by the ProcessInformation /// parameter should be large enough to hold a UNICODE_STRING structure as well as the string itself. The string stored in /// the Buffer member is the name of the image file. /// /// /// If the buffer is too small, the function fails with the STATUS_INFO_LENGTH_MISMATCH error code and the ReturnLength parameter is /// set to the required buffer size. /// /// /// The size of the buffer pointed to by the ProcessInformation parameter, in bytes. /// /// A pointer to a variable in which the function returns the size of the requested information. If the function was successful, /// this is the size of the information written to the buffer pointed to by the ProcessInformation parameter, but if the buffer was /// too small, this is the minimum size of buffer needed to receive the information successfully. /// /// /// The function returns an NTSTATUS success or error code. /// /// 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 under Kernel-Mode Driver Architecture / Design Guide / Driver Programming Techniques / /// Logging Errors. /// /// /// /// /// The NtQueryInformationProcess 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 /// public functions mentioned in the description of the ProcessInformationClass parameter instead. /// /// /// If you do use NtQueryInformationProcess, 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. /// /// /// This function has no associated import library. You must use the LoadLibrary and GetProcAddress functions to dynamically link to Ntdll.dll. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/winternl/nf-winternl-ntqueryinformationprocess __kernel_entry NTSTATUS // NtQueryInformationProcess( IN HANDLE ProcessHandle, IN PROCESSINFOCLASS ProcessInformationClass, OUT PVOID ProcessInformation, IN // ULONG ProcessInformationLength, OUT PULONG ReturnLength ); [DllImport(Lib.NtDll, SetLastError = false, ExactSpelling = true)] [PInvokeData("winternl.h", MSDNShortId = "0eae7899-c40b-4a5f-9e9c-adae021885e7")] public static extern NTStatus NtQueryInformationProcess([In] HPROCESS ProcessHandle, PROCESSINFOCLASS ProcessInformationClass, [Out] IntPtr ProcessInformation, uint ProcessInformationLength, out uint ReturnLength); /// /// Retrieves information about the specified process. /// /// The type of the structure to retrieve. /// A handle to the process for which information is to be retrieved. /// /// /// The type of process information to be retrieved. This parameter can be one of the following values from the /// PROCESSINFOCLASS enumeration. /// /// /// /// Value /// Meaning /// /// /// ProcessBasicInformation
0
/// /// Retrieves a pointer to a PEB structure that can be used to determine whether the specified process is being debugged, and a /// unique value used by the system to identify the specified process. Use the CheckRemoteDebuggerPresent and GetProcessId functions /// to obtain this information. /// ///
/// /// ProcessDebugPort
7
/// /// Retrieves a DWORD_PTR value that is the port number of the debugger for the process. A nonzero value indicates that the process /// is being run under the control of a ring 3 debugger. Use the CheckRemoteDebuggerPresent or IsDebuggerPresent function. /// ///
/// /// ProcessWow64Information
26
/// /// Determines whether the process is running in the WOW64 environment (WOW64 is the x86 emulator that allows Win32-based /// applications to run on 64-bit Windows). Use the IsWow64Process2 function to obtain this information. /// ///
/// /// ProcessImageFileName
27
/// /// Retrieves a UNICODE_STRING value containing the name of the image file for the process. Use the QueryFullProcessImageName or /// GetProcessImageFileName function to obtain this information. /// ///
/// /// ProcessBreakOnTermination
29
/// Retrieves a ULONG value indicating whether the process is considered critical. ///
/// /// ProcessSubsystemInformation
75
/// /// Retrieves a SUBSYSTEM_INFORMATION_TYPE value indicating the subsystem type of the process. The buffer pointed to by the /// ProcessInformation parameter should be large enough to hold a single SUBSYSTEM_INFORMATION_TYPE enumeration. /// ///
///
/// /// The structure and associated memory for any allocated sub-types. /// Mismatch between requested type and class. public static NtQueryResult NtQueryInformationProcess([In] HPROCESS ProcessHandle, PROCESSINFOCLASS ProcessInformationClass) where T : struct { var validTypes = CorrespondingTypeAttribute.GetCorrespondingTypes(ProcessInformationClass, CorrespondingAction.Get).ToArray(); if (validTypes.Length > 0 && Array.IndexOf(validTypes, typeof(T)) == -1) throw new ArgumentException("Mismatch between requested type and class."); #if x64 // Check if the target is a 32 bit process running in WoW64 mode. if (IsWow64(ProcessHandle)) { // We are 64 bit. Target process is 32 bit running in WoW64 mode. throw new PlatformNotSupportedException("Unable to query a 32-bit process from a 64-bit process."); } #else if (NtQueryInformationProcessRequiresWow64Structs(ProcessHandle)) { if (validTypes.Length > 1 && !TypeIsWow()) throw new ArgumentException("Type name must end in WOW64 to indicate it was configured exclusively for 64-bit use."); var mem = new NtQueryResult(); var status = NtWow64QueryInformationProcess64(ProcessHandle, ProcessInformationClass, ((IntPtr)mem).ToInt32(), mem.Size, out var sz); if (status.Succeeded) return mem; if (status != NTStatus.STATUS_INFO_LENGTH_MISMATCH || sz == 0) throw status.GetException(); mem.Size = sz; NtWow64QueryInformationProcess64(ProcessHandle, ProcessInformationClass, ((IntPtr)mem).ToInt32(), mem.Size, out _).ThrowIfFailed(); return mem; } #endif // Target process is of the same bitness as us. else { if (validTypes.Length > 1 && TypeIsWow()) throw new ArgumentException("Type name must not end in WOW64 should be configured for 32 or 64-bit use."); var mem = new NtQueryResult(); var status = NtQueryInformationProcess(ProcessHandle, ProcessInformationClass, mem, mem.Size, out var sz); if (status.Succeeded) return mem; if (status != NTStatus.STATUS_INFO_LENGTH_MISMATCH || sz == 0) throw status.GetException(); mem.Size = sz; NtQueryInformationProcess(ProcessHandle, ProcessInformationClass, mem, mem.Size, out _).ThrowIfFailed(); return mem; } bool TypeIsWow() => typeof(T).Name.EndsWith("WOW64"); } /// A call to NtQueryInformationProcess for the supplied process requires WOW64 structs. /// The process handle. /// if structures returned from NtQueryInformationProcess must be configured exclusively for 64-bit use. public static bool NtQueryInformationProcessRequiresWow64Structs(HPROCESS ProcessHandle) => IsWow64(Kernel32.GetCurrentProcess()) && !IsWow64(ProcessHandle); /// /// /// [ NtQueryInformationProcess may be altered or unavailable in future versions of Windows. Applications should use the /// alternate functions listed in this topic.] /// /// Retrieves information about the specified process. /// /// A handle to the process for which information is to be retrieved. /// /// /// The type of process information to be retrieved. This parameter can be one of the following values from the /// PROCESSINFOCLASS enumeration. /// /// /// /// Value /// Meaning /// /// /// ProcessBasicInformation
0
/// /// Retrieves a pointer to a PEB structure that can be used to determine whether the specified process is being debugged, and a /// unique value used by the system to identify the specified process. Use the CheckRemoteDebuggerPresent and GetProcessId functions /// to obtain this information. /// ///
/// /// ProcessDebugPort
7
/// /// Retrieves a DWORD_PTR value that is the port number of the debugger for the process. A nonzero value indicates that the process /// is being run under the control of a ring 3 debugger. Use the CheckRemoteDebuggerPresent or IsDebuggerPresent function. /// ///
/// /// ProcessWow64Information
26
/// /// Determines whether the process is running in the WOW64 environment (WOW64 is the x86 emulator that allows Win32-based /// applications to run on 64-bit Windows). Use the IsWow64Process2 function to obtain this information. /// ///
/// /// ProcessImageFileName
27
/// /// Retrieves a UNICODE_STRING value containing the name of the image file for the process. Use the QueryFullProcessImageName or /// GetProcessImageFileName function to obtain this information. /// ///
/// /// ProcessBreakOnTermination
29
/// Retrieves a ULONG value indicating whether the process is considered critical. ///
/// /// ProcessSubsystemInformation
75
/// /// Retrieves a SUBSYSTEM_INFORMATION_TYPE value indicating the subsystem type of the process. The buffer pointed to by the /// ProcessInformation parameter should be large enough to hold a single SUBSYSTEM_INFORMATION_TYPE enumeration. /// ///
///
/// /// /// /// A pointer to a buffer supplied by the calling application into which the function writes the requested information. The size of /// the information written varies depending on the data type of the ProcessInformationClass parameter: /// /// PROCESS_BASIC_INFORMATION /// /// When the ProcessInformationClass parameter is ProcessBasicInformation, the buffer pointed to by the ProcessInformation /// parameter should be large enough to hold a single PROCESS_BASIC_INFORMATION structure having the following layout: /// /// /// /// The UniqueProcessId member points to the system's unique identifier for this process. Use the GetProcessId function to /// retrieve this information. /// /// The PebBaseAddress member points to a PEB structure. /// The other members of this structure are reserved for internal use by the operating system. /// ULONG_PTR /// /// When the ProcessInformationClass parameter is ProcessWow64Information, the buffer pointed to by the ProcessInformation /// parameter should be large enough to hold a ULONG_PTR. If this value is nonzero, the process is running in a WOW64 /// environment; otherwise, if the value is equal to zero, the process is not running in a WOW64 environment. /// /// Use the IsWow64Process2 function to determine whether a process is running in the WOW64 environment. /// UNICODE_STRING /// /// When the ProcessInformationClass parameter is ProcessImageFileName, the buffer pointed to by the ProcessInformation /// parameter should be large enough to hold a UNICODE_STRING structure as well as the string itself. The string stored in /// the Buffer member is the name of the image file. /// /// /// If the buffer is too small, the function fails with the STATUS_INFO_LENGTH_MISMATCH error code and the ReturnLength parameter is /// set to the required buffer size. /// /// /// The size of the buffer pointed to by the ProcessInformation parameter, in bytes. /// /// A pointer to a variable in which the function returns the size of the requested information. If the function was successful, /// this is the size of the information written to the buffer pointed to by the ProcessInformation parameter, but if the buffer was /// too small, this is the minimum size of buffer needed to receive the information successfully. /// /// /// The function returns an NTSTATUS success or error code. /// /// 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 under Kernel-Mode Driver Architecture / Design Guide / Driver Programming Techniques / /// Logging Errors. /// /// /// /// /// The NtQueryInformationProcess 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 /// public functions mentioned in the description of the ProcessInformationClass parameter instead. /// /// /// If you do use NtQueryInformationProcess, 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. /// /// /// This function has no associated import library. You must use the LoadLibrary and GetProcAddress functions to dynamically link to Ntdll.dll. /// /// [DllImport(Lib.NtDll, SetLastError = false, ExactSpelling = true)] [PInvokeData("winternl.h")] public static extern NTStatus NtWow64QueryInformationProcess64([In] HPROCESS ProcessHandle, PROCESSINFOCLASS ProcessInformationClass, [Out] int ProcessInformation, [In] ulong ProcessInformationLength, out ulong ReturnLength); internal static bool IsWow64(HPROCESS hProc) => (Environment.OSVersion.Version.Major >= 6 || (Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor >= 1)) && Kernel32.IsWow64Process(hProc, out var b) && b; /// Timing information for a process. [StructLayout(LayoutKind.Sequential)] public struct KERNEL_USER_TIMES { /// The creation time of the process. public FILETIME CreateTime; /// The exit time of the process. public FILETIME ExitTime; /// /// The amount of time that the process has executed in kernel mode. The time that each of the threads of the process has /// executed in kernel mode is determined, and then all of those times are summed together to obtain this value. /// public FILETIME KernelTime; /// /// The amount of time that the process has executed in user mode. The time that each of the threads of the process has executed /// in user mode is determined, and then all of those times are summed together to obtain this value. Note that this value can /// exceed the amount of real time elapsed (between lpCreationTime and lpExitTime) if the process executes across multiple CPU cores. /// public FILETIME UserTime; } /// /// [This structure may be altered in future versions of Windows.] /// Contains process information. /// /// The syntax for this structure on 64-bit Windows is as follows: // https://docs.microsoft.com/en-us/windows/win32/api/winternl/ns-winternl-peb typedef struct _PEB { BYTE Reserved1[2]; BYTE // BeingDebugged; BYTE Reserved2[1]; PVOID Reserved3[2]; PPEB_LDR_DATA Ldr; PRTL_USER_PROCESS_PARAMETERS ProcessParameters; PVOID // Reserved4[3]; PVOID AtlThunkSListPtr; PVOID Reserved5; ULONG Reserved6; PVOID Reserved7; ULONG Reserved8; ULONG // AtlThunkSListPtr32; PVOID Reserved9[45]; BYTE Reserved10[96]; PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine; BYTE // Reserved11[128]; PVOID Reserved12[1]; ULONG SessionId; } PEB, *PPEB; [PInvokeData("winternl.h", MSDNShortId = "836a6b82-d3e8-4de6-808d-5476dfb51356")] [StructLayout(LayoutKind.Sequential)] public struct PEB { /// Reserved for internal use by the operating system. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] private readonly byte[] Reserved_1; /// Indicates whether the specified process is currently being debugged. public byte BeingDebugged; /// Reserved for internal use by the operating system. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] private readonly byte[] Reserved2; /// Reserved for internal use by the operating system. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] private readonly IntPtr[] Reserved3; /// A pointer to a PEB_LDR_DATA structure that contains information about the loaded modules for the process. public IntPtr Ldr; /// /// A pointer to an RTL_USER_PROCESS_PARAMETERS structure that contains process parameter information such as the command line. /// public IntPtr ProcessParameters; /// Reserved for internal use by the operating system. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] private readonly IntPtr[] Reserved4; private readonly IntPtr AtlThunkSListPtr; /// Reserved for internal use by the operating system. private readonly IntPtr Reserved5; /// Reserved for internal use by the operating system. private readonly uint Reserved6; /// Reserved for internal use by the operating system. private readonly IntPtr Reserved7; /// Reserved for internal use by the operating system. private readonly uint Reserved8; /// private readonly uint AtlThunkSListPtr32; /// Reserved for internal use by the operating system. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 45)] private readonly IntPtr[] Reserved9; /// Reserved for internal use by the operating system. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 96)] private readonly byte[] Reserved10; /// private readonly IntPtr PostProcessInitRoutine; /// Reserved for internal use by the operating system. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] private readonly byte[] Reserved11; /// Reserved for internal use by the operating system. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] private readonly IntPtr[] Reserved12; /// The Terminal Services session identifier associated with the current process. public uint SessionId; } /// /// [This structure may be altered in future versions of Windows.] /// Contains process information. /// /// The syntax for this structure on 64-bit Windows is as follows: // https://docs.microsoft.com/en-us/windows/win32/api/winternl/ns-winternl-peb typedef struct _PEB { BYTE Reserved1[2]; BYTE // BeingDebugged; BYTE Reserved2[1]; PVOID Reserved3[2]; PPEB_LDR_DATA Ldr; PRTL_USER_PROCESS_PARAMETERS ProcessParameters; PVOID // Reserved4[3]; PVOID AtlThunkSListPtr; PVOID Reserved5; ULONG Reserved6; PVOID Reserved7; ULONG Reserved8; ULONG // AtlThunkSListPtr32; PVOID Reserved9[45]; BYTE Reserved10[96]; PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine; BYTE // Reserved11[128]; PVOID Reserved12[1]; ULONG SessionId; } PEB, *PPEB; [PInvokeData("winternl.h", MSDNShortId = "836a6b82-d3e8-4de6-808d-5476dfb51356")] [StructLayout(LayoutKind.Sequential)] public struct PEB_WOW64 { /// Reserved for internal use by the operating system. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] private readonly byte[] Reserved_1; /// Indicates whether the specified process is currently being debugged. public byte BeingDebugged; /// Reserved for internal use by the operating system. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] private readonly byte[] Reserved2; /// Reserved for internal use by the operating system. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] private readonly long[] Reserved3; /// A pointer to a PEB_LDR_DATA structure that contains information about the loaded modules for the process. public long Ldr; /// /// A pointer to an RTL_USER_PROCESS_PARAMETERS structure that contains process parameter information such as the command line. /// public long ProcessParameters; /// Reserved for internal use by the operating system. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] private readonly long[] Reserved4; private readonly long AtlThunkSListPtr; /// Reserved for internal use by the operating system. private readonly long Reserved5; /// Reserved for internal use by the operating system. private readonly uint Reserved6; /// Reserved for internal use by the operating system. private readonly long Reserved7; /// Reserved for internal use by the operating system. private readonly uint Reserved8; /// private readonly uint AtlThunkSListPtr32; /// Reserved for internal use by the operating system. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 45)] private readonly long[] Reserved9; /// Reserved for internal use by the operating system. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 96)] private readonly byte[] Reserved10; /// private readonly long PostProcessInitRoutine; /// Reserved for internal use by the operating system. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] private readonly byte[] Reserved11; /// Reserved for internal use by the operating system. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] private readonly long[] Reserved12; /// The Terminal Services session identifier associated with the current process. public uint SessionId; } /// Contains information for basic process information. /// https://msdn.microsoft.com/en-us/library/windows/desktop/ms684280(v=vs.85).aspx [StructLayout(LayoutKind.Sequential)] public struct PROCESS_BASIC_INFORMATION { /// Reserved for internal use by the operating system. private readonly IntPtr Reserved1; /// Pointer to a PEB structure. public IntPtr PebBaseAddress; /// Reserved for internal use by the operating system. private readonly IntPtr Reserved2_1; /// Reserved for internal use by the operating system. private readonly IntPtr Reserved2_2; /// System's unique identifier for this process. public IntPtr UniqueProcessId; /// Reserved for internal use by the operating system. private readonly IntPtr Reserved3; } /// Contains information for basic process information. /// https://msdn.microsoft.com/en-us/library/windows/desktop/ms684280(v=vs.85).aspx [StructLayout(LayoutKind.Sequential)] public struct PROCESS_BASIC_INFORMATION_WOW64 { /// Reserved for internal use by the operating system. private readonly long Reserved1; /// Pointer to a PEB structure. public long PebBaseAddress; /// Reserved for internal use by the operating system. private readonly long Reserved2_1; /// Reserved for internal use by the operating system. private readonly long Reserved2_2; /// System's unique identifier for this process. public long UniqueProcessId; /// Reserved for internal use by the operating system. private readonly long Reserved3; } /// /// [This structure may be altered in future versions of Windows.] /// Contains process parameter information. /// // https://docs.microsoft.com/en-us/windows/win32/api/winternl/ns-winternl-rtl_user_process_parameters typedef struct // _RTL_USER_PROCESS_PARAMETERS { BYTE Reserved1[16]; PVOID Reserved2[10]; UNICODE_STRING ImagePathName; UNICODE_STRING CommandLine; // } RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS; [PInvokeData("winternl.h", MSDNShortId = "e736aefa-9945-4526-84d8-adb6e82b9991")] [StructLayout(LayoutKind.Sequential)] public struct RTL_USER_PROCESS_PARAMETERS { /// Reserved for internal use by the operating system. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] private readonly byte[] Reserved1; /// Reserved for internal use by the operating system. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] private readonly IntPtr[] Reserved2; /// The path of the image file for the process. public UNICODE_STRING ImagePathName; /// The command-line string passed to the process. public UNICODE_STRING CommandLine; } /// /// [This structure may be altered in future versions of Windows.] /// Contains process parameter information. /// // https://docs.microsoft.com/en-us/windows/win32/api/winternl/ns-winternl-rtl_user_process_parameters typedef struct // _RTL_USER_PROCESS_PARAMETERS { BYTE Reserved1[16]; PVOID Reserved2[10]; UNICODE_STRING ImagePathName; UNICODE_STRING CommandLine; // } RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS; [PInvokeData("winternl.h", MSDNShortId = "e736aefa-9945-4526-84d8-adb6e82b9991")] [StructLayout(LayoutKind.Sequential)] public struct RTL_USER_PROCESS_PARAMETERS_WOW64 { /// Reserved for internal use by the operating system. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] private readonly byte[] Reserved1; /// Reserved for internal use by the operating system. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] private readonly long[] Reserved2; /// The path of the image file for the process. public UNICODE_STRING_WOW64 ImagePathName; /// The command-line string passed to the process. public UNICODE_STRING_WOW64 CommandLine; } /// Returns the number of processors in the system. [PInvokeData("winternl.h", MSDNShortId = "553ec7b9-c5eb-4955-8dc0-f1c06f59fe31")] [StructLayout(LayoutKind.Sequential, Pack = 4)] public struct SYSTEM_BASIC_INFORMATION { /// Reserved. public ulong Reserved1_1; /// Reserved. public ulong Reserved1_2; /// Reserved. public ulong Reserved1_3; /// Reserved. public IntPtr Reserved2_1; /// Reserved. public IntPtr Reserved2_2; /// Reserved. public IntPtr Reserved2_3; /// Reserved. public IntPtr Reserved2_4; /// The number of processors present in the system. public byte NumberOfProcessors; } /// Process information. [PInvokeData("winternl.h", MSDNShortId = "553ec7b9-c5eb-4955-8dc0-f1c06f59fe31")] [StructLayout(LayoutKind.Sequential, Pack = 4)] public struct SYSTEM_PROCESS_INFORMATION { /// /// The start of the next item in the array is the address of the previous item plus the value in the NextEntryOffset member. /// For the last item in the array, NextEntryOffset is 0. /// public uint NextEntryOffset; /// The number of threads in the process. public uint NumberOfThreads; /// Reserved. public ulong Reserved1_1; /// Reserved. public ulong Reserved1_2; /// Reserved. public ulong Reserved1_3; /// Reserved. public ulong Reserved1_4; /// Reserved. public ulong Reserved1_5; /// Reserved. public ulong Reserved1_6; /// The process's image name. public UNICODE_STRING ImageName; /// The base priority of the process, which is the starting priority for threads created within the associated process. public int BasePriority; /// The process's unique process identifier. public IntPtr UniqueProcessId; /// Reserved. public IntPtr Reserved2; /// /// The total number of handles being used by the process in question; use GetProcessHandleCount to retrieve this information instead. /// public uint HandleCount; /// The session identifier of the process session. public uint SessionId; /// Reserved. public IntPtr Reserved3; /// The peak size, in bytes, of the virtual memory used by the process. public SizeT PeakVirtualSize; /// The current size, in bytes, of virtual memory used by the process. public SizeT VirtualSize; /// Reserved. public uint Reserved4; /// The peak size, in kilobytes, of the working set of the process. public SizeT PeakWorkingSetSize; /// The current quota charged to the process for paged pool usage. public SizeT WorkingSetSize; /// Reserved. public IntPtr Reserved5; /// The current quota charged to the process for paged pool usage. public SizeT QuotaPagedPoolUsage; /// Reserved. public IntPtr Reserved6; /// The current quota charged to the process for nonpaged pool usage. public SizeT QuotaNonPagedPoolUsage; /// The number of bytes of page file storage in use by the process. public SizeT PagefileUsage; /// The maximum number of bytes of page-file storage used by the process. public SizeT PeakPagefileUsage; /// The number of memory pages allocated for the use of this process. public SizeT PrivatePageCount; /// Reserved. public long Reserved7_1; /// Reserved. public long Reserved7_2; /// Reserved. public long Reserved7_3; /// Reserved. public long Reserved7_4; /// Reserved. public long Reserved7_5; /// Reserved. public long Reserved7_6; } /// Processor performance. [PInvokeData("winternl.h", MSDNShortId = "553ec7b9-c5eb-4955-8dc0-f1c06f59fe31")] [StructLayout(LayoutKind.Sequential, Pack = 8)] public struct SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION { /// The amount of time that the system has been idle, in 100-nanosecond intervals. public long IdleTime; /// /// 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.. /// public long KernelTime; /// /// 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. /// public long UserTime; /// Undocumented. public long DpcTime; /// Undocumented. public long InterruptTime; /// Reserved. public uint Reserved2; } /// Registry quota information. [PInvokeData("winternl.h", MSDNShortId = "553ec7b9-c5eb-4955-8dc0-f1c06f59fe31")] [StructLayout(LayoutKind.Sequential, Pack = 4)] public struct SYSTEM_REGISTRY_QUOTA_INFORMATION { /// The maximum size, in bytes, that the Registry can attain on this system. public uint RegistryQuotaAllowed; /// The current size of the Registry, in bytes. public uint RegistryQuotaUsed; /// Reserved. public IntPtr Reserved1; } /// Thread information. [PInvokeData("winternl.h", MSDNShortId = "553ec7b9-c5eb-4955-8dc0-f1c06f59fe31")] [StructLayout(LayoutKind.Sequential, Pack = 4)] public struct SYSTEM_THREAD_INFORMATION { /// Reserved. public ulong Reserved1_1; /// Reserved. public ulong Reserved1_2; /// Reserved. public ulong Reserved1_3; /// Reserved. public uint Reserved2; /// The start address of the thread. public IntPtr StartAddress; /// The ID of the thread and the process owning the thread. public CLIENT_ID ClientId; /// The dynamic thread priority. public int Priority; /// The base thread priority. public int BasePriority; /// Reserved. public uint Reserved3; /// The current thread state. public uint ThreadState; /// The reason the thread is waiting. public uint WaitReason; } /// /// Represents the structure and associated memory returned by NtQueryXX functions. The memory associate with this structure /// will be disposed when this variable goes out of scope or is disposed. /// /// The type of the retrieved structure. public class NtQueryResult : SafeMemStruct where T : struct { internal NtQueryResult(uint sz = 0) : base(sz) { } } } }