using System; using System.Collections.Generic; using System.Runtime.InteropServices; using Vanara.InteropServices; using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME; namespace Vanara.PInvoke { public static partial class Kernel32 { /// The resolution in microseconds of the performance counters in PSS_PERFORMANCE_COUNTERS. [PInvokeData("processsnapshot.h")] public const uint PSS_PERF_RESOLUTION = 1000000; /// /// Flags that specify what PssCaptureSnapshot captures. /// /// /// /// If both PSS_CREATE_FORCE_BREAKAWAY and PSS_CREATE_BREAKAWAY are specified, then PSS_CREATE_FORCE_BREAKAWAY /// takes precedence. /// /// // https://docs.microsoft.com/en-us/previous-versions/windows/desktop/api/processsnapshot/ne-processsnapshot-pss_capture_flags // typedef enum PSS_CAPTURE_FLAGS { PSS_CAPTURE_NONE , PSS_CAPTURE_VA_CLONE , PSS_CAPTURE_RESERVED_00000002 , PSS_CAPTURE_HANDLES , // PSS_CAPTURE_HANDLE_NAME_INFORMATION , PSS_CAPTURE_HANDLE_BASIC_INFORMATION , PSS_CAPTURE_HANDLE_TYPE_SPECIFIC_INFORMATION , // PSS_CAPTURE_HANDLE_TRACE , PSS_CAPTURE_THREADS , PSS_CAPTURE_THREAD_CONTEXT , PSS_CAPTURE_THREAD_CONTEXT_EXTENDED , // PSS_CAPTURE_RESERVED_00000400 , PSS_CAPTURE_VA_SPACE , PSS_CAPTURE_VA_SPACE_SECTION_INFORMATION , PSS_CAPTURE_IPT_TRACE , // PSS_CREATE_BREAKAWAY_OPTIONAL , PSS_CREATE_BREAKAWAY , PSS_CREATE_FORCE_BREAKAWAY , PSS_CREATE_USE_VM_ALLOCATIONS , // PSS_CREATE_MEASURE_PERFORMANCE , PSS_CREATE_RELEASE_SECTION } ; [PInvokeData("processsnapshot.h", MSDNShortId = "6146DDA2-2475-45F8-86F3-65791B10743D")] [Flags] public enum PSS_CAPTURE_FLAGS : uint { /// Capture nothing. PSS_CAPTURE_NONE = 0x00000000, /// /// Capture a snapshot of all cloneable pages in the process. The clone includes all MEM_PRIVATE regions, as well as all sections /// (MEM_MAPPED and MEM_IMAGE) that are shareable. All Win32 sections created via CreateFileMapping are shareable. /// PSS_CAPTURE_VA_CLONE = 0x00000001, /// (Do not use.) PSS_CAPTURE_RESERVED_00000002 = 0x00000002, /// Capture the handle table (handle values only). PSS_CAPTURE_HANDLES = 0x00000004, /// Capture name information for each handle. PSS_CAPTURE_HANDLE_NAME_INFORMATION = 0x00000008, /// Capture basic handle information such as HandleCount, PointerCount, GrantedAccess, etc. PSS_CAPTURE_HANDLE_BASIC_INFORMATION = 0x00000010, /// Capture type-specific information for supported object types: Process, Thread, Event, Mutant, Section. PSS_CAPTURE_HANDLE_TYPE_SPECIFIC_INFORMATION = 0x00000020, /// Capture the handle tracing table. PSS_CAPTURE_HANDLE_TRACE = 0x00000040, /// Capture thread information (IDs only). PSS_CAPTURE_THREADS = 0x00000080, /// Capture the context for each thread. PSS_CAPTURE_THREAD_CONTEXT = 0x00000100, /// Capture extended context for each thread (e.g. CONTEXT_XSTATE). PSS_CAPTURE_THREAD_CONTEXT_EXTENDED = 0x00000200, /// (Do not use.) PSS_CAPTURE_RESERVED_00000400 = 0x00000400, /// /// Capture a snapshot of the virtual address space. The VA space is captured as an array of MEMORY_BASIC_INFORMATION structures. /// This flag does not capture the contents of the pages. /// PSS_CAPTURE_VA_SPACE = 0x00000800, /// /// For MEM_IMAGE and MEM_MAPPED regions, dumps the path to the file backing the sections (identical to what GetMappedFileName /// returns). For MEM_IMAGE regions, also dumps: The PROCESS_VM_READ access right is required on the process handle. /// PSS_CAPTURE_VA_SPACE_SECTION_INFORMATION = 0x00001000, /// PSS_CAPTURE_IPT_TRACE = 0x00002000, /// /// The breakaway is optional. If the clone process fails to create as a breakaway, then it is created still inside the job. This /// flag must be specified in combination with either PSS_CREATE_FORCE_BREAKAWAY and/or PSS_CREATE_BREAKAWAY. /// PSS_CREATE_BREAKAWAY_OPTIONAL = 0x04000000, /// The clone is broken away from the parent process' job. This is equivalent to CreateProcess flag CREATE_BREAKAWAY_FROM_JOB. PSS_CREATE_BREAKAWAY = 0x08000000, /// The clone is forcefully broken away the parent process's job. This is only allowed for Tcb-privileged callers. PSS_CREATE_FORCE_BREAKAWAY = 0x10000000, /// /// The facility should not use the process heap for any persistent or transient allocations. The use of the heap may be /// undesirable in certain contexts such as creation of snapshots in the exception reporting path (where the heap may be corrupted). /// PSS_CREATE_USE_VM_ALLOCATIONS = 0x20000000, /// /// Measure performance of the facility. Performance counters can be retrieved via PssQuerySnapshot with the /// PSS_QUERY_PERFORMANCE_COUNTERS information class of PSS_QUERY_INFORMATION_CLASS. /// PSS_CREATE_MEASURE_PERFORMANCE = 0x40000000, /// /// The virtual address (VA) clone process does not hold a reference to the underlying image. This will cause functions such as /// QueryFullProcessImageName to fail on the VA clone process. /// PSS_CREATE_RELEASE_SECTION = 0x80000000 } /// /// Duplication flags for use by PssDuplicateSnapshot. /// // https://docs.microsoft.com/en-us/previous-versions/windows/desktop/api/processsnapshot/ne-processsnapshot-pss_duplicate_flags // typedef enum PSS_DUPLICATE_FLAGS { PSS_DUPLICATE_NONE , PSS_DUPLICATE_CLOSE_SOURCE } ; [PInvokeData("processsnapshot.h", MSDNShortId = "CAD06441-750F-42FC-A95A-7CAA79F31348")] [Flags] public enum PSS_DUPLICATE_FLAGS { /// No flag. PSS_DUPLICATE_NONE = 0x00, /// /// Free the source handle. This will only succeed if you set the PSS_CREATE_USE_VM_ALLOCATIONS flag when you called /// PssCaptureSnapshot to create the snapshot and handle. The handle will be freed even if duplication fails. The close operation /// does not protect against concurrent access to the same descriptor. /// PSS_DUPLICATE_CLOSE_SOURCE = 0x01 } /// /// Flags to specify what parts of a PSS_HANDLE_ENTRY structure are valid. /// // https://docs.microsoft.com/en-us/previous-versions/windows/desktop/api/processsnapshot/ne-processsnapshot-pss_handle_flags typedef // enum PSS_HANDLE_FLAGS { PSS_HANDLE_NONE , PSS_HANDLE_HAVE_TYPE , PSS_HANDLE_HAVE_NAME , PSS_HANDLE_HAVE_BASIC_INFORMATION , // PSS_HANDLE_HAVE_TYPE_SPECIFIC_INFORMATION } ; [PInvokeData("processsnapshot.h", MSDNShortId = "A4A604A9-0210-413C-BCAC-F8458B371D42")] [Flags] public enum PSS_HANDLE_FLAGS { /// No parts specified. PSS_HANDLE_NONE = 0x00, /// The ObjectType member is valid. PSS_HANDLE_HAVE_TYPE = 0x01, /// The ObjectName member is valid. PSS_HANDLE_HAVE_NAME = 0x02, /// /// The Attributes, GrantedAccess, HandleCount, PointerCount, PagedPoolCharge, and NonPagedPoolCharge members are valid. /// PSS_HANDLE_HAVE_BASIC_INFORMATION = 0x04, /// The TypeSpecificInformation member is valid (either Process, Thread, Mutant, Event or Section). PSS_HANDLE_HAVE_TYPE_SPECIFIC_INFORMATION = 0x08 } /// /// Specifies the object type in a PSS_HANDLE_ENTRY structure. /// // https://docs.microsoft.com/en-us/previous-versions/windows/desktop/api/processsnapshot/ne-processsnapshot-pss_object_type typedef // enum PSS_OBJECT_TYPE { PSS_OBJECT_TYPE_UNKNOWN , PSS_OBJECT_TYPE_PROCESS , PSS_OBJECT_TYPE_THREAD , PSS_OBJECT_TYPE_MUTANT , // PSS_OBJECT_TYPE_EVENT , PSS_OBJECT_TYPE_SECTION , PSS_OBJECT_TYPE_SEMAPHORE } ; [PInvokeData("processsnapshot.h", MSDNShortId = "3AF2AE47-6E1A-4B20-B6A3-36C1DDB80674")] public enum PSS_OBJECT_TYPE { /// The object type is either unknown or unsupported. PSS_OBJECT_TYPE_UNKNOWN, /// The object is a process. PSS_OBJECT_TYPE_PROCESS, /// The object is a thread. PSS_OBJECT_TYPE_THREAD, /// The object is a mutant/mutex. PSS_OBJECT_TYPE_MUTANT, /// The object is an event. PSS_OBJECT_TYPE_EVENT, /// The object is a file-mapping object. PSS_OBJECT_TYPE_SECTION, /// PSS_OBJECT_TYPE_SEMAPHORE, } /// /// Flags that describe a process. /// /// /// There are PSS_PROCESS_FLAGS members in the PSS_PROCESS_INFORMATION and PSS_HANDLE_ENTRY structures. /// // https://docs.microsoft.com/en-us/previous-versions/windows/desktop/api/processsnapshot/ne-processsnapshot-pss_process_flags // typedef enum PSS_PROCESS_FLAGS { PSS_PROCESS_FLAGS_NONE , PSS_PROCESS_FLAGS_PROTECTED , PSS_PROCESS_FLAGS_WOW64 , // PSS_PROCESS_FLAGS_RESERVED_03 , PSS_PROCESS_FLAGS_RESERVED_04 , PSS_PROCESS_FLAGS_FROZEN } ; [PInvokeData("processsnapshot.h", MSDNShortId = "A1C793DD-EE93-47B6-8EA8-3A45DAD55F2D")] [Flags] public enum PSS_PROCESS_FLAGS { /// No flag. PSS_PROCESS_FLAGS_NONE = 0x00000000, /// The process is protected. PSS_PROCESS_FLAGS_PROTECTED = 0x00000001, /// The process is a 32-bit process running on a 64-bit native OS. PSS_PROCESS_FLAGS_WOW64 = 0x00000002, /// Undefined. PSS_PROCESS_FLAGS_RESERVED_03 = 0x00000004, /// Undefined. PSS_PROCESS_FLAGS_RESERVED_04 = 0x00000008, /// /// The process is frozen; for example, a debugger is attached and broken into the process or a Store process is suspended by a /// lifetime management service. /// PSS_PROCESS_FLAGS_FROZEN = 0x00000010 } /// /// Specifies what information PssQuerySnapshot function returns. /// // https://docs.microsoft.com/en-us/previous-versions/windows/desktop/api/processsnapshot/ne-processsnapshot-pss_query_information_class // typedef enum PSS_QUERY_INFORMATION_CLASS { PSS_QUERY_PROCESS_INFORMATION , PSS_QUERY_VA_CLONE_INFORMATION , // PSS_QUERY_AUXILIARY_PAGES_INFORMATION , PSS_QUERY_VA_SPACE_INFORMATION , PSS_QUERY_HANDLE_INFORMATION , // PSS_QUERY_THREAD_INFORMATION , PSS_QUERY_HANDLE_TRACE_INFORMATION , PSS_QUERY_PERFORMANCE_COUNTERS } ; [PInvokeData("processsnapshot.h", MSDNShortId = "1C3E5BF4-5AC9-4012-B29D-49C35C0AF90B")] public enum PSS_QUERY_INFORMATION_CLASS { /// Returns a PSS_PROCESS_INFORMATION structure, with information about the original process. [CorrespondingType(typeof(PSS_PROCESS_INFORMATION), CorrespondingAction.Get)] PSS_QUERY_PROCESS_INFORMATION, /// Returns a PSS_VA_CLONE_INFORMATION structure, with a handle to the VA clone. [CorrespondingType(typeof(PSS_VA_CLONE_INFORMATION), CorrespondingAction.Get)] PSS_QUERY_VA_CLONE_INFORMATION, /// Returns a PSS_AUXILIARY_PAGES_INFORMATION structure, which contains the count of auxiliary pages captured. [CorrespondingType(typeof(PSS_AUXILIARY_PAGES_INFORMATION), CorrespondingAction.Get)] PSS_QUERY_AUXILIARY_PAGES_INFORMATION, /// Returns a PSS_VA_SPACE_INFORMATION structure, which contains the count of regions captured. [CorrespondingType(typeof(PSS_VA_SPACE_INFORMATION), CorrespondingAction.Get)] PSS_QUERY_VA_SPACE_INFORMATION, /// Returns a PSS_HANDLE_INFORMATION structure, which contains the count of handles captured. [CorrespondingType(typeof(PSS_HANDLE_INFORMATION), CorrespondingAction.Get)] PSS_QUERY_HANDLE_INFORMATION, /// Returns a PSS_THREAD_INFORMATION structure, which contains the count of threads captured. [CorrespondingType(typeof(PSS_THREAD_INFORMATION), CorrespondingAction.Get)] PSS_QUERY_THREAD_INFORMATION, /// /// Returns a PSS_HANDLE_TRACE_INFORMATION structure, which contains a handle to the handle trace section, and its size. /// [CorrespondingType(typeof(PSS_HANDLE_TRACE_INFORMATION), CorrespondingAction.Get)] PSS_QUERY_HANDLE_TRACE_INFORMATION, /// Returns a PSS_PERFORMANCE_COUNTERS structure, which contains various performance counters. [CorrespondingType(typeof(PSS_PERFORMANCE_COUNTERS), CorrespondingAction.Get)] PSS_QUERY_PERFORMANCE_COUNTERS, } /// /// Flags that describe a thread. /// /// /// There is a PSS_THREAD_FLAGS member in the PSS_THREAD_ENTRY structure that PssWalkSnapshot returns. /// // https://docs.microsoft.com/en-us/previous-versions/windows/desktop/api/processsnapshot/ne-processsnapshot-pss_thread_flags typedef // enum PSS_THREAD_FLAGS { PSS_THREAD_FLAGS_NONE , PSS_THREAD_FLAGS_TERMINATED } ; [PInvokeData("processsnapshot.h", MSDNShortId = "8E90F0EA-D50A-431D-9507-B882EB673629")] [Flags] public enum PSS_THREAD_FLAGS { /// No flag. PSS_THREAD_FLAGS_NONE = 0x0000, /// The thread terminated. PSS_THREAD_FLAGS_TERMINATED = 0x0001 } /// /// Specifies what information the PssWalkSnapshot function returns. /// // https://docs.microsoft.com/en-us/previous-versions/windows/desktop/api/processsnapshot/ne-processsnapshot-pss_walk_information_class // typedef enum PSS_WALK_INFORMATION_CLASS { PSS_WALK_AUXILIARY_PAGES , PSS_WALK_VA_SPACE , PSS_WALK_HANDLES , PSS_WALK_THREADS } ; [PInvokeData("processsnapshot.h", MSDNShortId = "93A79F7F-2164-4F7A-ADE7-C1655EEFC9BF")] public enum PSS_WALK_INFORMATION_CLASS { /// /// Returns a PSS_AUXILIARY_PAGE_ENTRY structure, which contains the address, page attributes and contents of an auxiliary copied page. /// [CorrespondingType(typeof(PSS_AUXILIARY_PAGE_ENTRY), CorrespondingAction.Get)] PSS_WALK_AUXILIARY_PAGES, /// /// Returns a PSS_VA_SPACE_ENTRY structure, which contains the MEMORY_BASIC_INFORMATION structure for every distinct VA region. /// [CorrespondingType(typeof(PSS_VA_SPACE_ENTRY), CorrespondingAction.Get)] PSS_WALK_VA_SPACE, /// /// Returns a PSS_HANDLE_ENTRY structure, with information specifying the handle value, its type name, object name (if captured), /// basic information (if captured), and type-specific information (if captured). /// [CorrespondingType(typeof(PSS_HANDLE_ENTRY), CorrespondingAction.Get)] PSS_WALK_HANDLES, /// /// Returns a PSS_THREAD_ENTRY structure, with basic information about the thread, as well as its termination state, suspend /// count and Win32 start address. /// [CorrespondingType(typeof(PSS_THREAD_ENTRY), CorrespondingAction.Get)] PSS_WALK_THREADS, } /// /// Captures a snapshot of a target process. /// /// /// A handle to the target process. /// /// /// Flags that specify what to capture. For more information, see PSS_CAPTURE_FLAGS. /// /// /// The CONTEXT record flags to capture if CaptureFlags specifies thread contexts. /// /// /// A handle to the snapshot that this function captures. /// /// /// This function returns ERROR_SUCCESS on success. /// /// All error codes are defined in winerror.h. Use FormatMessage with the FORMAT_MESSAGE_FROM_SYSTEM flag to get a message for /// an error code. /// /// // https://docs.microsoft.com/en-us/previous-versions/windows/desktop/api/processsnapshot/nf-processsnapshot-psscapturesnapshot DWORD // PssCaptureSnapshot( HANDLE ProcessHandle, PSS_CAPTURE_FLAGS CaptureFlags, DWORD ThreadContextFlags, HPSS *SnapshotHandle ); [PInvokeData("processsnapshot.h", MSDNShortId = "44F2CB48-A9F6-4131-B21C-9F27A27CECD5")] public static Win32Error PssCaptureSnapshot(HPROCESS ProcessHandle, PSS_CAPTURE_FLAGS CaptureFlags, uint ThreadContextFlags, out SafeHPSS SnapshotHandle) { var err = PssCaptureSnapshotInternal(ProcessHandle, CaptureFlags, ThreadContextFlags, out SnapshotHandle); SnapshotHandle.ProcessHandle = ProcessHandle; return err; } /// /// Duplicates a snapshot handle from one process to another. /// /// /// /// A handle to the source process from which the original snapshot was captured. The handle must have PROCESS_VM_READ and /// PROCESS_DUP_HANDLE rights. /// /// /// /// A handle to the snapshot to duplicate. This handle must be in the context of the source process. /// /// /// /// A handle to the target process that receives the duplicate snapshot. The handle must have PROCESS_VM_OPERATION, /// PROCESS_VM_WRITE, and PROCESS_DUP_HANDLE rights. /// /// /// /// A handle to the duplicate snapshot that this function creates, in the context of the target process. /// /// /// The duplication flags. For more information, see PSS_DUPLICATE_FLAGS. /// /// /// This function returns ERROR_SUCCESS on success or the following error code. /// /// /// Return code /// Description /// /// /// ERROR_INVALID_HANDLE /// The specified handle is invalid. /// /// /// /// All error codes are defined in winerror.h. Use FormatMessage with the FORMAT_MESSAGE_FROM_SYSTEM flag to get a message for /// an error code. /// /// // https://docs.microsoft.com/en-us/previous-versions/windows/desktop/api/processsnapshot/nf-processsnapshot-pssduplicatesnapshot // DWORD PssDuplicateSnapshot( HANDLE SourceProcessHandle, HPSS SnapshotHandle, HANDLE TargetProcessHandle, HPSS // *TargetSnapshotHandle, PSS_DUPLICATE_FLAGS Flags ); [PInvokeData("processsnapshot.h", MSDNShortId = "5D2751F3-E7E1-4917-8060-E2BC8A7A3DEA")] public static Win32Error PssDuplicateSnapshot(HPROCESS SourceProcessHandle, HPSS SnapshotHandle, HPROCESS TargetProcessHandle, out SafeHPSS TargetSnapshotHandle, PSS_DUPLICATE_FLAGS Flags) { var err = PssDuplicateSnapshot(SourceProcessHandle, SnapshotHandle, TargetProcessHandle, out TargetSnapshotHandle, Flags); TargetSnapshotHandle.ProcessHandle = TargetProcessHandle; return err; } /// /// Frees a snapshot. /// /// /// /// A handle to the process that contains the snapshot. The handle must have PROCESS_VM_READ, PROCESS_VM_OPERATION, and /// PROCESS_DUP_HANDLE rights. If the snapshot was captured from the current process, or duplicated into the current process, /// then pass in the result of GetCurrentProcess. /// /// /// /// A handle to the snapshot to free. /// /// /// This function returns ERROR_SUCCESS on success or one of the following error codes. /// /// /// Return code /// Description /// /// /// ERROR_INVALID_HANDLE /// The specified handle is invalid. /// /// /// ERROR_NOT_SUPPORTED /// The remote snapshot was not created with PSS_CREATE_USE_VM_ALLOCATIONS. /// /// /// /// All error codes are defined in winerror.h. Use FormatMessage with the FORMAT_MESSAGE_FROM_SYSTEM flag to get a message for /// an error code. /// /// /// /// /// This API can free snapshot handles in the context of either the local or remote processes. If the snapshot was captured in the /// local process with PssCaptureSnapshot, or duplicated into the local process with PssDuplicateSnapshot, then specify the result of /// GetCurrentProcess as the process handle. If the snapshot is in the context of a remote process (for example, duplicated into the /// remote process), then specify the handle to that process. /// /// The operation does not protect against concurrent access to the same descriptor. /// /// For remote process frees, only snapshot handles that were created with PSS_CREATE_USE_VM_ALLOCATIONS or duplicated /// remotely can be freed by this API. /// /// The behavior of this routine on a descriptor that has already been freed is undefined. /// // https://docs.microsoft.com/en-us/previous-versions/windows/desktop/api/processsnapshot/nf-processsnapshot-pssfreesnapshot DWORD // PssFreeSnapshot( HANDLE ProcessHandle, HPSS SnapshotHandle ); [DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)] [PInvokeData("processsnapshot.h", MSDNShortId = "5D062AE6-2F7C-4121-AB6E-9BFA06AB36C6")] public static extern Win32Error PssFreeSnapshot(HPROCESS ProcessHandle, HPSS SnapshotHandle); /// Queries the snapshot. /// A handle to the snapshot to query. /// An enumerator member that selects what information to query. For more information, see PSS_QUERY_INFORMATION_CLASS. /// The information that this function provides. /// The size of Buffer, in bytes. /// /// This function returns ERROR_SUCCESS on success or one of the following error codes. /// /// /// Return code /// Description /// /// /// ERROR_BAD_LENGTH /// The specified buffer length is invalid. /// /// /// ERROR_INVALID_HANDLE /// The specified handle is invalid. /// /// /// ERROR_INVALID_PARAMETER /// The specified information class is invalid. /// /// /// ERROR_NOT_FOUND /// The requested information is not in the snapshot. /// /// /// /// All error codes are defined in winerror.h. Use FormatMessage with the FORMAT_MESSAGE_FROM_SYSTEM flag to get a message for /// an error code. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/processsnapshot/nf-processsnapshot-pssquerysnapshot DWORD PssQuerySnapshot( // HPSS SnapshotHandle, PSS_QUERY_INFORMATION_CLASS InformationClass, void *Buffer, DWORD BufferLength ); [DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)] [PInvokeData("processsnapshot.h", MSDNShortId = "D9580147-28ED-4FF5-B7DB-844ACB19769F")] public static extern Win32Error PssQuerySnapshot(HPSS SnapshotHandle, PSS_QUERY_INFORMATION_CLASS InformationClass, IntPtr Buffer, uint BufferLength); /// Queries the snapshot. /// The type of the information to retrieve specified by . /// A handle to the snapshot to query. /// An enumerator member that selects what information to query. For more information, see PSS_QUERY_INFORMATION_CLASS. /// The information that this function provides. /// InformationClass public static T PssQuerySnapshot(HPSS SnapshotHandle, PSS_QUERY_INFORMATION_CLASS InformationClass) where T : struct { if (!CorrespondingTypeAttribute.CanGet(InformationClass, typeof(T))) throw new ArgumentOutOfRangeException(nameof(InformationClass)); using (var mem = SafeCoTaskMemHandle.CreateFromStructure()) { PssQuerySnapshot(SnapshotHandle, InformationClass, (IntPtr)mem, (uint)mem.Size).ThrowIfFailed(); return mem.ToStructure(); } } /// /// Creates a walk marker. /// /// /// /// A structure that provides functions to allocate and free memory. If you provide the structure, PssWalkMarkerCreate uses /// the functions to allocate the internal walk marker structures. Otherwise it uses the default process heap. For more information, /// see PSS_ALLOCATOR. /// /// /// /// A handle to the walk marker that this function creates. /// /// /// This function returns ERROR_SUCCESS on success or the following error code. /// /// /// Return code /// Description /// /// /// ERROR_NOT_ENOUGH_MEMORY /// Could not allocate memory for the walk marker. /// /// /// /// All error codes are defined in winerror.h. Use FormatMessage with the FORMAT_MESSAGE_FROM_SYSTEM flag to get a message for /// an error code. /// /// /// /// The walk marker maintains the state of a walk, and can be used to reposition or rewind the walk. /// /// The Allocator structure that provides the custom functions should remain valid for the lifetime of the walk marker. The custom /// functions are called from PssWalkMarkerCreate, PssWalkMarkerFree and PssWalkSnapshot using the same thread that calls /// PssWalkMarkerCreate, PssWalkMarkerFree and PssWalkSnapshot. Therefore the custom functions need not be multi-threaded. /// /// // https://docs.microsoft.com/en-us/previous-versions/windows/desktop/api/processsnapshot/nf-processsnapshot-psswalkmarkercreate // DWORD PssWalkMarkerCreate( PSS_ALLOCATOR const *Allocator, HPSSWALK *WalkMarkerHandle ); [DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)] [PInvokeData("processsnapshot.h", MSDNShortId = "58E2FBAF-661C-45BE-A25A-A096AF52ED3E")] public static extern Win32Error PssWalkMarkerCreate(in PSS_ALLOCATOR Allocator, out SafeHPSSWALK WalkMarkerHandle); /// /// Creates a walk marker. /// /// /// /// A structure that provides functions to allocate and free memory. If you provide the structure, PssWalkMarkerCreate uses /// the functions to allocate the internal walk marker structures. Otherwise it uses the default process heap. For more information, /// see PSS_ALLOCATOR. /// /// /// /// A handle to the walk marker that this function creates. /// /// /// This function returns ERROR_SUCCESS on success or the following error code. /// /// /// Return code /// Description /// /// /// ERROR_NOT_ENOUGH_MEMORY /// Could not allocate memory for the walk marker. /// /// /// /// All error codes are defined in winerror.h. Use FormatMessage with the FORMAT_MESSAGE_FROM_SYSTEM flag to get a message for /// an error code. /// /// /// /// The walk marker maintains the state of a walk, and can be used to reposition or rewind the walk. /// /// The Allocator structure that provides the custom functions should remain valid for the lifetime of the walk marker. The custom /// functions are called from PssWalkMarkerCreate, PssWalkMarkerFree and PssWalkSnapshot using the same thread that calls /// PssWalkMarkerCreate, PssWalkMarkerFree and PssWalkSnapshot. Therefore the custom functions need not be multi-threaded. /// /// // https://docs.microsoft.com/en-us/previous-versions/windows/desktop/api/processsnapshot/nf-processsnapshot-psswalkmarkercreate // DWORD PssWalkMarkerCreate( PSS_ALLOCATOR const *Allocator, HPSSWALK *WalkMarkerHandle ); [DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)] [PInvokeData("processsnapshot.h", MSDNShortId = "58E2FBAF-661C-45BE-A25A-A096AF52ED3E")] public static extern Win32Error PssWalkMarkerCreate([Optional] IntPtr Allocator, out SafeHPSSWALK WalkMarkerHandle); /// /// Frees a walk marker created by PssWalkMarkerCreate. /// /// /// A handle to the walk marker. /// /// /// This function returns ERROR_SUCCESS on success. /// /// All error codes are defined in winerror.h. Use FormatMessage with the FORMAT_MESSAGE_FROM_SYSTEM flag to get a message for /// an error code. /// /// /// /// /// If PssWalkMarkerCreate used AllocRoutine of a custom allocator to create the walk marker, PssWalkMarkerFree uses /// the FreeRoutine of the allocator. /// /// // https://docs.microsoft.com/en-us/previous-versions/windows/desktop/api/processsnapshot/nf-processsnapshot-psswalkmarkerfree DWORD // PssWalkMarkerFree( HPSSWALK WalkMarkerHandle ); [DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)] [PInvokeData("processsnapshot.h", MSDNShortId = "74158846-6A5F-4F81-B4D7-46DED1EE017C")] public static extern Win32Error PssWalkMarkerFree(HPSSWALK WalkMarkerHandle); /// /// Returns the current position of a walk marker. /// /// /// A handle to the walk marker. /// /// /// The walk marker position that this function returns. /// /// /// This function returns ERROR_SUCCESS on success. /// /// All error codes are defined in winerror.h. Use FormatMessage with the FORMAT_MESSAGE_FROM_SYSTEM flag to get a message for /// an error code. /// /// /// /// /// The position value compared to the values of other positions is not of any significance. The only valid use of the position is to /// set the current position using the PssWalkMarkerSetPosition function. /// /// // https://docs.microsoft.com/en-us/previous-versions/windows/desktop/api/processsnapshot/nf-processsnapshot-psswalkmarkergetposition // DWORD PssWalkMarkerGetPosition( HPSSWALK WalkMarkerHandle, ULONG_PTR *Position ); [DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)] [PInvokeData("processsnapshot.h", MSDNShortId = "A2058E81-2B01-4436-ACC6-2A3E58BC4E27")] public static extern Win32Error PssWalkMarkerGetPosition(HPSSWALK WalkMarkerHandle, out UIntPtr Position); /// /// Rewinds a walk marker back to the beginning. /// /// /// A handle to the walk marker. /// /// /// This function returns ERROR_SUCCESS on success. /// /// All error codes are defined in winerror.h. Use FormatMessage with the FORMAT_MESSAGE_FROM_SYSTEM flag to get a message for /// an error code. /// /// // https://docs.microsoft.com/en-us/previous-versions/windows/desktop/api/processsnapshot/nf-processsnapshot-psswalkmarkerseektobeginning // DWORD PssWalkMarkerSeekToBeginning( HPSSWALK WalkMarkerHandle ); [DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)] [PInvokeData("processsnapshot.h", MSDNShortId = "BE0FA122-3966-4827-9DA3-A98A162EF270")] public static extern Win32Error PssWalkMarkerSeekToBeginning(HPSSWALK WalkMarkerHandle); /// /// Sets the position of a walk marker. /// /// /// A handle to the walk marker. /// /// /// The position to set. This is a position that the PssWalkMarkerGetPosition function provided. /// /// /// This function returns ERROR_SUCCESS on success or one of the following error codes. /// /// All error codes are defined in winerror.h. Use FormatMessage with the FORMAT_MESSAGE_FROM_SYSTEM flag to get a message for /// an error code. /// /// // https://docs.microsoft.com/en-us/previous-versions/windows/desktop/api/processsnapshot/nf-processsnapshot-psswalkmarkersetposition // DWORD PssWalkMarkerSetPosition( HPSSWALK WalkMarkerHandle, ULONG_PTR Position ); [DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)] [PInvokeData("processsnapshot.h", MSDNShortId = "D89EA4DB-D8C6-43D1-B292-D24F1EAB2E43")] public static extern Win32Error PssWalkMarkerSetPosition(HPSSWALK WalkMarkerHandle, UIntPtr Position); /// /// Returns information from the current walk position and advanced the walk marker to the next position. /// /// /// A handle to the snapshot. /// /// /// The type of information to return. For more information, see PSS_WALK_INFORMATION_CLASS. /// /// /// /// A handle to a walk marker. The walk marker indicates the walk position from which data is to be returned. PssWalkSnapshot /// advances the walk marker to the next walk position in time order before returning to the caller. /// /// /// /// The snapshot information that this function returns. /// /// /// The size of Buffer, in bytes. /// /// /// This function returns ERROR_SUCCESS on success or one of the following error codes. /// /// /// Return code /// Description /// /// /// ERROR_BAD_LENGTH /// The specified buffer length is invalid. /// /// /// ERROR_INVALID_HANDLE /// The specified handle is invalid. /// /// /// ERROR_INVALID_PARAMETER /// The specified information class is invalid. /// /// /// ERROR_MORE_DATA /// Buffer is NULL, and there is data at the current position to return. /// /// /// ERROR_NO_MORE_ITEMS /// The walk has completed and there are no more items to return. /// /// /// ERROR_NOT_FOUND /// The requested information is not in the snapshot. /// /// /// /// All error codes are defined in winerror.h. Use FormatMessage with the FORMAT_MESSAGE_FROM_SYSTEM flag to get a message for /// an error code. /// /// /// /// /// For snapshot data types that have a variable number of instances within a snapshot, you use the PssWalkSnapshot function /// to obtain the instances one after another. You set the InformationClass parameter to specify the type of data. /// /// // https://docs.microsoft.com/en-us/previous-versions/windows/desktop/api/processsnapshot/nf-processsnapshot-psswalksnapshot DWORD // PssWalkSnapshot( HPSS SnapshotHandle, PSS_WALK_INFORMATION_CLASS InformationClass, HPSSWALK WalkMarkerHandle, void *Buffer, DWORD // BufferLength ); [DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)] [PInvokeData("processsnapshot.h", MSDNShortId = "C6AC38B5-0A1C-44D7-A1F6-8196AE9B8FB0")] public static extern Win32Error PssWalkSnapshot(HPSS SnapshotHandle, PSS_WALK_INFORMATION_CLASS InformationClass, HPSSWALK WalkMarkerHandle, IntPtr Buffer, uint BufferLength); /// Returns information from the current walk position and advanced the walk marker to the next position. /// A handle to the snapshot. /// The type of information to return. For more information, see PSS_WALK_INFORMATION_CLASS. /// /// An optional handle to a walk marker. The walk marker indicates the walk position from which data is to be returned. PssWalkSnapshot /// advances the walk marker to the next walk position in time order before returning to the caller. /// If this value is NULL, then a new walk marker will be temporarily created. /// /// The list of snapshot information that this function returns. [PInvokeData("processsnapshot.h", MSDNShortId = "C6AC38B5-0A1C-44D7-A1F6-8196AE9B8FB0")] public static IEnumerable PssWalkSnapshot(HPSS SnapshotHandle, PSS_WALK_INFORMATION_CLASS InformationClass, HPSSWALK WalkMarkerHandle = default) where T : struct { if (!CorrespondingTypeAttribute.CanGet(InformationClass, typeof(T))) throw new ArgumentOutOfRangeException(nameof(InformationClass)); if (SnapshotHandle.IsNull) throw new ArgumentNullException(nameof(SnapshotHandle)); SafeHPSSWALK hWalk; if (WalkMarkerHandle.IsNull) PssWalkMarkerCreate(IntPtr.Zero, out hWalk).ThrowIfFailed(); else hWalk = new SafeHPSSWALK(WalkMarkerHandle.DangerousGetHandle(), false); using (hWalk) using (var mem = SafeCoTaskMemHandle.CreateFromStructure()) { do { var err = PssWalkSnapshot(SnapshotHandle, InformationClass, hWalk, (IntPtr)mem, (uint)mem.Size); if (err == Win32Error.ERROR_NO_MORE_ITEMS) break; else err.ThrowIfFailed(); yield return mem.ToStructure(); } while (true); } } [DllImport(Lib.Kernel32, SetLastError = false, EntryPoint = "PssCaptureSnapshot", ExactSpelling = true)] private static extern Win32Error PssCaptureSnapshotInternal(HPROCESS ProcessHandle, PSS_CAPTURE_FLAGS CaptureFlags, uint ThreadContextFlags, out SafeHPSS SnapshotHandle); [DllImport(Lib.Kernel32, SetLastError = false, EntryPoint = "PssDuplicateSnapshot", ExactSpelling = true)] private static extern Win32Error PssDuplicateSnapshotInternal(HPROCESS SourceProcessHandle, HPSS SnapshotHandle, HPROCESS TargetProcessHandle, out SafeHPSS TargetSnapshotHandle, PSS_DUPLICATE_FLAGS Flags); /// Provides a handle to a target snapshot. [StructLayout(LayoutKind.Sequential)] public struct HPSS : IHandle { private IntPtr handle; /// Initializes a new instance of the struct. /// An object that represents the pre-existing handle to use. public HPSS(IntPtr preexistingHandle) => handle = preexistingHandle; /// Returns an invalid handle by instantiating a object with . public static HPSS NULL => new HPSS(IntPtr.Zero); /// Gets a value indicating whether this instance is a null handle. public bool IsNull => handle == IntPtr.Zero; /// Performs an explicit conversion from to . /// The handle. /// The result of the conversion. public static explicit operator IntPtr(HPSS h) => h.handle; /// Performs an implicit conversion from to . /// The pointer to a handle. /// The result of the conversion. public static implicit operator HPSS(IntPtr h) => new HPSS(h); /// Implements the operator !=. /// The first handle. /// The second handle. /// The result of the operator. public static bool operator !=(HPSS h1, HPSS h2) => !(h1 == h2); /// Implements the operator ==. /// The first handle. /// The second handle. /// The result of the operator. public static bool operator ==(HPSS h1, HPSS h2) => h1.Equals(h2); /// public override bool Equals(object obj) => obj is HPSS h ? handle == h.handle : false; /// public override int GetHashCode() => handle.GetHashCode(); /// public IntPtr DangerousGetHandle() => handle; } /// Provides a handle to a wall marker. [StructLayout(LayoutKind.Sequential)] public struct HPSSWALK : IHandle { private IntPtr handle; /// Initializes a new instance of the struct. /// An object that represents the pre-existing handle to use. public HPSSWALK(IntPtr preexistingHandle) => handle = preexistingHandle; /// Returns an invalid handle by instantiating a object with . public static HPSSWALK NULL => new HPSSWALK(IntPtr.Zero); /// Gets a value indicating whether this instance is a null handle. public bool IsNull => handle == IntPtr.Zero; /// Performs an explicit conversion from to . /// The handle. /// The result of the conversion. public static explicit operator IntPtr(HPSSWALK h) => h.handle; /// Performs an implicit conversion from to . /// The pointer to a handle. /// The result of the conversion. public static implicit operator HPSSWALK(IntPtr h) => new HPSSWALK(h); /// Implements the operator !=. /// The first handle. /// The second handle. /// The result of the operator. public static bool operator !=(HPSSWALK h1, HPSSWALK h2) => !(h1 == h2); /// Implements the operator ==. /// The first handle. /// The second handle. /// The result of the operator. public static bool operator ==(HPSSWALK h1, HPSSWALK h2) => h1.Equals(h2); /// public override bool Equals(object obj) => obj is HPSSWALK h ? handle == h.handle : false; /// public override int GetHashCode() => handle.GetHashCode(); /// public IntPtr DangerousGetHandle() => handle; } /// /// /// Contains information about a range of pages in the virtual address space of a process. The VirtualQuery and VirtualQueryEx /// functions use this structure. /// /// /// /// /// To enable a debugger to debug a target that is running on a different architecture (32-bit versus 64-bit), use one of the /// explicit forms of this structure. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/winnt/ns-winnt-_memory_basic_information typedef struct // _MEMORY_BASIC_INFORMATION { PVOID BaseAddress; PVOID AllocationBase; DWORD AllocationProtect; SIZE_T RegionSize; DWORD State; // DWORD Protect; DWORD Type; } MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION; [PInvokeData("winnt.h", MSDNShortId = "dc3fa48e-0986-49cc-88a9-ff8179fbe5f0")] [StructLayout(LayoutKind.Sequential)] public struct MEMORY_BASIC_INFORMATION { /// /// A pointer to the base address of the region of pages. /// public IntPtr BaseAddress; /// /// /// A pointer to the base address of a range of pages allocated by the VirtualAlloc function. The page pointed to by the /// BaseAddress member is contained within this allocation range. /// /// public IntPtr AllocationBase; /// /// /// The memory protection option when the region was initially allocated. This member can be one of the memory protection /// constants or 0 if the caller does not have access. /// /// public uint AllocationProtect; /// /// The size of the region beginning at the base address in which all pages have identical attributes, in bytes. /// public SizeT RegionSize; /// /// The state of the pages in the region. This member can be one of the following values. /// /// /// State /// Meaning /// /// /// MEM_COMMIT 0x1000 /// /// Indicates committed pages for which physical storage has been allocated, either in memory or in the paging file on disk. /// /// /// /// MEM_FREE 0x10000 /// /// Indicates free pages not accessible to the calling process and available to be allocated. For free pages, the information in /// the AllocationBase, AllocationProtect, Protect, and Type members is undefined. /// /// /// /// MEM_RESERVE 0x2000 /// /// Indicates reserved pages where a range of the process's virtual address space is reserved without any physical storage being /// allocated. For reserved pages, the information in the Protect member is undefined. /// /// /// /// public uint State; /// /// /// The access protection of the pages in the region. This member is one of the values listed for the AllocationProtect member. /// /// public uint Protect; /// /// The type of pages in the region. The following types are defined. /// /// /// Type /// Meaning /// /// /// MEM_IMAGE 0x1000000 /// Indicates that the memory pages within the region are mapped into the view of an image section. /// /// /// MEM_MAPPED 0x40000 /// Indicates that the memory pages within the region are mapped into the view of a section. /// /// /// MEM_PRIVATE 0x20000 /// Indicates that the memory pages within the region are private (that is, not shared by other processes). /// /// /// public uint Type; } /// /// /// Specifies custom functions which the Process Snapshotting functions use to allocate and free the internal walk marker structures. /// /// /// /// /// To use custom memory allocation functions, pass this structure to PssWalkMarkerCreate. Otherwise, the Process Snapshotting /// functions use the default process heap. /// /// /// The PSS_ALLOCATOR structure that provides the custom functions should remain valid for the lifetime of the walk marker /// that PssWalkMarkerCreate creates. /// /// FreeRoutine must accept NULL address parameters without failing. /// /// The custom functions are called from PssWalkMarkerCreate, PssWalkMarkerFree and PssWalkSnapshot using the same thread that calls /// PssWalkMarkerCreate, PssWalkMarkerFree and PssWalkSnapshot. Therefore the custom functions need not be multi-threaded. /// /// // https://docs.microsoft.com/en-us/previous-versions/windows/desktop/api/processsnapshot/ns-processsnapshot-pss_allocator typedef // struct PSS_ALLOCATOR { void *Context; void )(void *Context,DWORD Size) *(*AllocRoutine; void((void *Context, void *Address) * // )FreeRoutine; }; [PInvokeData("processsnapshot.h", MSDNShortId = "54225F76-9A2E-4CB3-A3B5-9F9DB5551D53")] [StructLayout(LayoutKind.Sequential)] public struct PSS_ALLOCATOR { /// /// An arbitrary pointer-sized value that the Process Snapshotting functions pass to AllocRoutine and FreeRoutine. /// public IntPtr Context; /// /// /// A pointer to a WINAPI-calling convention function that takes two parameters. It returns a pointer to the block of memory that /// it allocates, or NULL if allocation fails. /// /// Context /// The context value, as passed in PSS_ALLOCATOR. /// Size /// Number of bytes to allocate. /// [MarshalAs(UnmanagedType.FunctionPtr)] public AllocRoutine Alloc; /// /// /// A pointer to a WINAPI-calling convention function taking two parameters. It deallocates a block of memory that /// AllocRoutine allocated. /// /// Context /// The context value, as passed in PSS_ALLOCATOR. /// Address /// The address of a block of memory that AllocRoutine allocated. /// [MarshalAs(UnmanagedType.FunctionPtr)] public FreeRoutine Free; /// A WINAPI-calling convention function that takes two parameters. /// The context. /// The size. /// A pointer to the block of memory that it allocates, or NULL if allocation fails. [UnmanagedFunctionPointer(CallingConvention.Winapi)] public delegate IntPtr AllocRoutine(IntPtr Context, uint Size); /// A WINAPI-calling convention function taking two parameters. /// The context. /// The address. [UnmanagedFunctionPointer(CallingConvention.Winapi)] public delegate void FreeRoutine(IntPtr Context, IntPtr Address); } /// /// Holds auxiliary page entry information returned by PssWalkSnapshot. /// /// /// /// PssWalkSnapshot returns a PSS_AUXILIARY_PAGE_ENTRY structure when the PSS_WALK_INFORMATION_CLASS member that the caller /// provides it is PSS_WALK_AUXILIARY_PAGES. /// /// // https://docs.microsoft.com/en-us/previous-versions/windows/desktop/api/processsnapshot/ns-processsnapshot-pss_auxiliary_page_entry // typedef struct PSS_AUXILIARY_PAGE_ENTRY { void *Address; MEMORY_BASIC_INFORMATION BasicInformation; FILETIME CaptureTime; void // *PageContents; DWORD PageSize; }; [PInvokeData("processsnapshot.h", MSDNShortId = "A3D948E6-6FFE-4732-A8C7-A292FDA07D7C")] [StructLayout(LayoutKind.Sequential)] public struct PSS_AUXILIARY_PAGE_ENTRY { /// /// The address of the captured auxiliary page, in the context of the captured process. /// public IntPtr Address; /// /// Basic information about the captured page. See MEMORY_BASIC_INFORMATION for more information. /// public MEMORY_BASIC_INFORMATION BasicInformation; /// /// The capture time of the page. For more information, see FILETIME. /// public FILETIME CaptureTime; /// /// /// A pointer to the contents of the captured page, in the context of the current process. This member may be NULL if page /// contents were not captured. The pointer is valid for the lifetime of the walk marker passed to PssWalkSnapshot. /// /// public IntPtr PageContents; /// /// The size of the page contents that PageContents points to, in bytes. /// public uint PageSize; } /// Holds auxiliary pages information returned by PssQuerySnapshot. /// /// PssQuerySnapshot returns a PSS_AUXILIARY_PAGES_INFORMATION structure when the PSS_QUERY_INFORMATION_CLASS member that the /// caller provides it is PSS_QUERY_AUXILIARY_PAGES_INFORMATION. /// // https://docs.microsoft.com/en-us/previous-versions/windows/desktop/api/processsnapshot/ns-processsnapshot-pss_auxiliary_pages_information // typedef struct PSS_AUXILIARY_PAGES_INFORMATION { DWORD AuxPagesCaptured; }; [PInvokeData("processsnapshot.h", MSDNShortId = "122DD3DF-002A-4250-9E37-BA239638A684")] [StructLayout(LayoutKind.Sequential)] public struct PSS_AUXILIARY_PAGES_INFORMATION { /// /// The count of auxiliary pages captured. /// public uint AuxPagesCaptured; } /// /// Holds information about a handle returned by PssWalkSnapshot. /// /// /// /// PssWalkSnapshot returns a PSS_HANDLE_ENTRY structure when the PSS_WALK_INFORMATION_CLASS member that the caller provides /// it is PSS_WALK_HANDLES. /// /// // https://docs.microsoft.com/en-us/previous-versions/windows/desktop/api/processsnapshot/ns-processsnapshot-pss_handle_entry typedef // struct PSS_HANDLE_ENTRY { HANDLE Handle; PSS_HANDLE_FLAGS Flags; PSS_OBJECT_TYPE ObjectType; FILETIME CaptureTime; DWORD // Attributes; DWORD GrantedAccess; DWORD HandleCount; DWORD PointerCount; DWORD PagedPoolCharge; DWORD NonPagedPoolCharge; FILETIME // CreationTime; WORD TypeNameLength; wchar_t const *TypeName; WORD ObjectNameLength; wchar_t const *ObjectName; union { struct { // DWORD ExitStatus; void *PebBaseAddress; ULONG_PTR AffinityMask; LONG BasePriority; DWORD ProcessId; DWORD ParentProcessId; DWORD // Flags; } Process; struct { DWORD ExitStatus; void *TebBaseAddress; DWORD ProcessId; DWORD ThreadId; ULONG_PTR AffinityMask; int // Priority; int BasePriority; void *Win32StartAddress; } Thread; struct { LONG CurrentCount; BOOL Abandoned; DWORD OwnerProcessId; // DWORD OwnerThreadId; } Mutant; struct { BOOL ManualReset; BOOL Signaled; } Event; struct { void *BaseAddress; DWORD // AllocationAttributes; LARGE_INTEGER MaximumSize; } Section; struct { LONG CurrentCount; LONG MaximumCount; } Semaphore; } // TypeSpecificInformation; }; [PInvokeData("processsnapshot.h", MSDNShortId = "F56E8C35-949A-4DEE-973F-CF24F6596036")] [StructLayout(LayoutKind.Sequential)] public struct PSS_HANDLE_ENTRY { /// /// The handle value. /// public IntPtr Handle; /// /// Flags that indicate what parts of this structure are valid. For more information, see PSS_HANDLE_FLAGS. /// public PSS_HANDLE_FLAGS Flags; /// /// The type of the object that the handle references. For more information, see PSS_OBJECT_TYPE. /// public PSS_OBJECT_TYPE ObjectType; /// /// The capture time of this information. For more information, see FILETIME. /// public FILETIME CaptureTime; /// /// Attributes. /// public uint Attributes; /// /// Reserved for use by the operating system. /// public uint GrantedAccess; /// /// Reserved for use by the operating system. /// public uint HandleCount; /// /// Reserved for use by the operating system. /// public uint PointerCount; /// /// Reserved for use by the operating system. /// public uint PagedPoolCharge; /// /// Reserved for use by the operating system. /// public uint NonPagedPoolCharge; /// /// Reserved for use by the operating system. /// public FILETIME CreationTime; /// /// The length of TypeName, in bytes. /// public ushort TypeNameLength; /// /// /// The type name of the object referenced by this handle. The buffer may not terminated by a NULL character. The pointer /// is valid for the lifetime of the walk marker passed to PssWalkSnapshot. /// /// public IntPtr TypeName; /// /// The length of ObjectName, in bytes. /// public ushort ObjectNameLength; /// /// /// Specifies the name of the object referenced by this handle. The buffer may not terminated by a NULL character. The /// pointer is valid for the lifetime of the walk marker passed to PssWalkSnapshot. /// /// public IntPtr ObjectName; /// /// Type-specific information. /// public UNION TypeSpecificInformation; /// /// Type-specific information. /// [StructLayout(LayoutKind.Explicit)] public struct UNION { /// Process [FieldOffset(0)] public Process Process; /// Thread [FieldOffset(0)] public Thread Thread; /// Mutant [FieldOffset(0)] public Mutant Mutant; /// Event [FieldOffset(0)] public Event Event; /// Section [FieldOffset(0)] public Section Section; /// Semaphore [FieldOffset(0)] public Semaphore Semaphore; } /// Undocumented. [StructLayout(LayoutKind.Sequential)] public struct Process { /// /// The exit code of the process. If the process has not exited, this is set to STILL_ACTIVE (259). /// public uint ExitStatus; /// /// The address of the process environment block (PEB). Reserved for use by the operating system. /// public IntPtr PebBaseAddress; /// /// The affinity mask of the process. /// public UIntPtr AffinityMask; /// /// The base priority level of the process. /// public int BasePriority; /// /// The process ID. /// public uint ProcessId; /// /// The parent process ID. /// public uint ParentProcessId; /// /// Flags about the process. For more information, see PSS_PROCESS_FLAGS. /// public uint Flags; } /// Undocumented. [StructLayout(LayoutKind.Sequential)] public struct Thread { /// /// The exit code of the process. If the process has not exited, this is set to STILL_ACTIVE (259). /// public uint ExitStatus; /// /// The address of the thread environment block (TEB). Reserved for use by the operating system. /// public IntPtr TebBaseAddress; /// /// The process ID. /// public uint ProcessId; /// /// The thread ID. /// public uint ThreadId; /// /// The affinity mask of the process. /// public UIntPtr AffinityMask; /// /// The thread’s dynamic priority level. /// public int Priority; /// /// The thread’s base priority level. /// public int BasePriority; /// /// A pointer to the thread procedure for the thread. /// public IntPtr Win32StartAddress; } /// Undocumented. [StructLayout(LayoutKind.Sequential)] public struct Mutant { /// /// Reserved for use by the operating system. /// public int CurrentCount; /// /// /// TRUE if the mutant has been abandoned (the owning thread exited without releasing the mutex), FALSE if not. /// /// [MarshalAs(UnmanagedType.Bool)] public bool Abandoned; /// /// The process ID of the owning thread, at the time of snapshot creation and handle capture. /// public uint OwnerProcessId; /// /// The process ID of the owning thread, at the time of snapshot creation and handle capture. /// public uint OwnerThreadId; } /// Undocumented. [StructLayout(LayoutKind.Sequential)] public struct Event { /// /// TRUE if the event is manual reset, FALSE if not. /// [MarshalAs(UnmanagedType.Bool)] public bool ManualReset; /// /// TRUE if the event was signaled at the time of snapshot creation and handle capture, FALSE if not. /// [MarshalAs(UnmanagedType.Bool)] public bool Signaled; } /// Undocumented. [StructLayout(LayoutKind.Sequential)] public struct Section { /// /// Reserved for use by the operating system. /// public IntPtr BaseAddress; /// /// Reserved for use by the operating system. /// public uint AllocationAttributes; /// /// Reserved for use by the operating system. /// public long MaximumSize; } /// Undocumented. [StructLayout(LayoutKind.Sequential)] public struct Semaphore { /// Undocumented. public int CurrentCount; /// Undocumented. public int MaximumCount; } } /// /// Holds handle information returned by PssQuerySnapshot. /// /// /// /// PssQuerySnapshot returns a PSS_HANDLE_INFORMATION structure when the PSS_QUERY_INFORMATION_CLASS member that the caller /// provides it is PSS_QUERY_HANDLE_INFORMATION. /// /// // https://docs.microsoft.com/en-us/previous-versions/windows/desktop/api/processsnapshot/ns-processsnapshot-pss_handle_information // typedef struct PSS_HANDLE_INFORMATION { DWORD HandlesCaptured; }; [PInvokeData("processsnapshot.h", MSDNShortId = "77192849-D919-4947-9BFF-343C166C5A51")] [StructLayout(LayoutKind.Sequential)] public struct PSS_HANDLE_INFORMATION { /// /// The count of handles captured. /// public uint HandlesCaptured; } /// Holds handle trace information returned by PssQuerySnapshot. /// /// PssQuerySnapshot returns a PSS_HANDLE_TRACE_INFORMATION structure when the PSS_QUERY_INFORMATION_CLASS member that the /// caller provides it is PSS_QUERY_HANDLE_TRACE_INFORMATION. /// // https://docs.microsoft.com/en-us/windows/desktop/api/processsnapshot/ns-processsnapshot-pss_handle_trace_information typedef // struct { HANDLE SectionHandle; DWORD Size; } PSS_HANDLE_TRACE_INFORMATION; [PInvokeData("processsnapshot.h", MSDNShortId = "0877DF1F-044C-48F2-9BCC-938EBD6D46EE")] [StructLayout(LayoutKind.Sequential)] public struct PSS_HANDLE_TRACE_INFORMATION { /// A handle to a section containing the handle trace information. public HANDLE SectionHandle; /// The size of the handle trace section, in bytes. public uint Size; } /// /// Holds performance counters returned by PssQuerySnapshot. /// /// /// /// PssQuerySnapshot returns a PSS_PERFORMANCE_COUNTERS structure when the PSS_QUERY_INFORMATION_CLASS member that the caller /// provides it is PSS_QUERY_PERFORMANCE_COUNTERS. /// /// // https://docs.microsoft.com/en-us/previous-versions/windows/desktop/api/processsnapshot/ns-processsnapshot-pss_performance_counters // typedef struct PSS_PERFORMANCE_COUNTERS { UINT64 TotalCycleCount; UINT64 TotalWallClockPeriod; UINT64 VaCloneCycleCount; UINT64 // VaCloneWallClockPeriod; UINT64 VaSpaceCycleCount; UINT64 VaSpaceWallClockPeriod; UINT64 AuxPagesCycleCount; UINT64 // AuxPagesWallClockPeriod; UINT64 HandlesCycleCount; UINT64 HandlesWallClockPeriod; UINT64 ThreadsCycleCount; UINT64 // ThreadsWallClockPeriod; }; [PInvokeData("processsnapshot.h", MSDNShortId = "298C1FC8-D19D-4DB3-84AA-3870D06B16A1")] [StructLayout(LayoutKind.Sequential)] public struct PSS_PERFORMANCE_COUNTERS { /// /// The count of clock cycles spent for capture. /// public ulong TotalCycleCount; /// /// The count of FILETIME units spent for capture. /// public ulong TotalWallClockPeriod; /// /// The count of clock cycles spent for the capture of the VA clone. /// public ulong VaCloneCycleCount; /// /// The count of FILETIME units spent for the capture of the VA clone. /// public ulong VaCloneWallClockPeriod; /// /// The count of clock cycles spent for the capture of VA space information. /// public ulong VaSpaceCycleCount; /// /// The count of FILETIME units spent for the capture VA space information. /// public ulong VaSpaceWallClockPeriod; /// /// The count of clock cycles spent for the capture of auxiliary page information. /// public ulong AuxPagesCycleCount; /// /// The count of FILETIME units spent for the capture of auxiliary page information. /// public ulong AuxPagesWallClockPeriod; /// /// The count of clock cycles spent for the capture of handle information. /// public ulong HandlesCycleCount; /// /// The count of FILETIME units spent for the capture of handle information. /// public ulong HandlesWallClockPeriod; /// /// The count of clock cycles spent for the capture of thread information. /// public ulong ThreadsCycleCount; /// /// The count of FILETIME units spent for the capture of thread information. /// public ulong ThreadsWallClockPeriod; } /// /// Holds process information returned by PssQuerySnapshot. /// /// /// /// PssQuerySnapshot returns a PSS_PROCESS_INFORMATION structure when the PSS_QUERY_INFORMATION_CLASS member that the caller /// provides it is PSS_QUERY_PROCESS_INFORMATION. /// /// // https://docs.microsoft.com/en-us/previous-versions/windows/desktop/api/processsnapshot/ns-processsnapshot-pss_process_information // typedef struct PSS_PROCESS_INFORMATION { DWORD ExitStatus; void *PebBaseAddress; ULONG_PTR AffinityMask; LONG BasePriority; DWORD // ProcessId; DWORD ParentProcessId; PSS_PROCESS_FLAGS Flags; FILETIME CreateTime; FILETIME ExitTime; FILETIME KernelTime; FILETIME // UserTime; DWORD PriorityClass; ULONG_PTR PeakVirtualSize; ULONG_PTR VirtualSize; DWORD PageFaultCount; ULONG_PTR // PeakWorkingSetSize; ULONG_PTR WorkingSetSize; ULONG_PTR QuotaPeakPagedPoolUsage; ULONG_PTR QuotaPagedPoolUsage; ULONG_PTR // QuotaPeakNonPagedPoolUsage; ULONG_PTR QuotaNonPagedPoolUsage; ULONG_PTR PagefileUsage; ULONG_PTR PeakPagefileUsage; ULONG_PTR // PrivateUsage; DWORD ExecuteFlags; wchar_t ImageFileName[MAX_PATH]; }; [PInvokeData("processsnapshot.h", MSDNShortId = "D629FA42-B501-4A0E-9B53-6D70E580B687")] [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct PSS_PROCESS_INFORMATION { /// /// The exit code of the process. If the process has not exited, this is set to STILL_ACTIVE (259). /// public uint ExitStatus; /// /// The address to the process environment block (PEB). Reserved for use by the operating system. /// public IntPtr PebBaseAddress; /// /// The affinity mask of the process. /// public UIntPtr AffinityMask; /// /// The base priority level of the process. /// public int BasePriority; /// /// The process ID. /// public uint ProcessId; /// /// The parent process ID. /// public uint ParentProcessId; /// /// Flags about the process. For more information, see PSS_PROCESS_FLAGS. /// public PSS_PROCESS_FLAGS Flags; /// /// The time the process was created. For more information, see FILETIME. /// public FILETIME CreateTime; /// /// If the process exited, the time of the exit. For more information, see FILETIME. /// public FILETIME ExitTime; /// /// The amount of time the process spent executing in kernel-mode. For more information, see FILETIME. /// public FILETIME KernelTime; /// /// The amount of time the process spent executing in user-mode. For more information, see FILETIME. /// public FILETIME UserTime; /// /// The priority class. /// public uint PriorityClass; /// /// A memory usage counter. See the GetProcessMemoryInfo function for more information. /// public UIntPtr PeakVirtualSize; /// /// A memory usage counter. See the GetProcessMemoryInfo function for more information. /// public UIntPtr VirtualSize; /// /// A memory usage counter. See the GetProcessMemoryInfo function for more information. /// public uint PageFaultCount; /// /// A memory usage counter. See the GetProcessMemoryInfo function for more information. /// public UIntPtr PeakWorkingSetSize; /// /// A memory usage counter. See the GetProcessMemoryInfo function for more information. /// public UIntPtr WorkingSetSize; /// /// A memory usage counter. See the GetProcessMemoryInfo function for more information. /// public UIntPtr QuotaPeakPagedPoolUsage; /// /// A memory usage counter. See the GetProcessMemoryInfo function for more information. /// public UIntPtr QuotaPagedPoolUsage; /// /// A memory usage counter. See the GetProcessMemoryInfo function for more information. /// public UIntPtr QuotaPeakNonPagedPoolUsage; /// /// A memory usage counter. See the GetProcessMemoryInfo function for more information. /// public UIntPtr QuotaNonPagedPoolUsage; /// /// A memory usage counter. See the GetProcessMemoryInfo function for more information. /// public UIntPtr PagefileUsage; /// /// A memory usage counter. See the GetProcessMemoryInfo function for more information. /// public UIntPtr PeakPagefileUsage; /// /// A memory usage counter. See the GetProcessMemoryInfo function for more information. /// public UIntPtr PrivateUsage; /// /// Reserved for use by the operating system. /// public uint ExecuteFlags; /// /// The full path to the process executable. If the path exceeds the allocated buffer size, it is truncated. /// [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)] public string ImageFileName; } /// /// Holds thread information returned by PssWalkSnapshot PssWalkSnapshot. /// /// /// /// PssWalkSnapshot returns a PSS_THREAD_ENTRY structure when the PSS_WALK_INFORMATION_CLASS member that the caller provides /// it is PSS_WALK_THREADS. /// /// // https://docs.microsoft.com/en-us/previous-versions/windows/desktop/api/processsnapshot/ns-processsnapshot-pss_thread_entry typedef // struct PSS_THREAD_ENTRY { DWORD ExitStatus; void *TebBaseAddress; DWORD ProcessId; DWORD ThreadId; ULONG_PTR AffinityMask; int // Priority; int BasePriority; void *LastSyscallFirstArgument; WORD LastSyscallNumber; FILETIME CreateTime; FILETIME ExitTime; // FILETIME KernelTime; FILETIME UserTime; void *Win32StartAddress; FILETIME CaptureTime; PSS_THREAD_FLAGS Flags; WORD SuspendCount; // WORD SizeOfContextRecord; PCONTEXT ContextRecord; }; [PInvokeData("processsnapshot.h", MSDNShortId = "99C89DBB-8C12-482E-B33D-AE59C37662CF")] [StructLayout(LayoutKind.Sequential)] public struct PSS_THREAD_ENTRY { /// /// The exit code of the process. If the process has not exited, this is set to STILL_ACTIVE (259). /// public uint ExitStatus; /// /// The address of the thread environment block (TEB). Reserved for use by the operating system. /// public IntPtr TebBaseAddress; /// /// The process ID. /// public uint ProcessId; /// /// The thread ID. /// public uint ThreadId; /// /// The affinity mask of the process. /// public UIntPtr AffinityMask; /// /// The thread’s dynamic priority level. /// public int Priority; /// /// The base priority level of the process. /// public int BasePriority; /// /// Reserved for use by the operating system. /// public IntPtr LastSyscallFirstArgument; /// /// Reserved for use by the operating system. /// public ushort LastSyscallNumber; /// /// The time the thread was created. For more information, see FILETIME. /// public FILETIME CreateTime; /// /// If the thread exited, the time of the exit. For more information, see FILETIME. /// public FILETIME ExitTime; /// /// The amount of time the thread spent executing in kernel mode. For more information, see FILETIME. /// public FILETIME KernelTime; /// /// The amount of time the thread spent executing in user mode. For more information, see FILETIME. /// public FILETIME UserTime; /// /// A pointer to the thread procedure for thread. /// public IntPtr Win32StartAddress; /// /// The capture time of this thread. For more information, see FILETIME. /// public FILETIME CaptureTime; /// /// Flags about the thread. For more information, see PSS_THREAD_FLAGS. /// public PSS_THREAD_FLAGS Flags; /// /// The count of times the thread suspended. /// public ushort SuspendCount; /// /// The size of ContextRecord, in bytes. /// public ushort SizeOfContextRecord; /// /// /// A pointer to the context record if thread context information was captured. The pointer is valid for the lifetime of the walk /// marker passed to PssWalkSnapshot. /// /// public IntPtr ContextRecord; // valid for life time of walk marker } /// /// Holds thread information returned by PssQuerySnapshot. /// /// /// /// PssQuerySnapshot returns a PSS_THREAD_INFORMATION structure when the PSS_QUERY_INFORMATION_CLASS member that the caller /// provides it is PSS_QUERY_THREAD_INFORMATION. /// /// // https://docs.microsoft.com/en-us/previous-versions/windows/desktop/api/processsnapshot/ns-processsnapshot-pss_thread_information // typedef struct PSS_THREAD_INFORMATION { DWORD ThreadsCaptured; DWORD ContextLength; }; [PInvokeData("processsnapshot.h", MSDNShortId = "68BC42FD-9A30-462F-AFB1-DF9587C50F45")] [StructLayout(LayoutKind.Sequential)] public struct PSS_THREAD_INFORMATION { /// /// The count of threads in the snapshot. /// public uint ThreadsCaptured; /// /// The length of the CONTEXT record captured, in bytes. /// public uint ContextLength; } /// /// Holds virtual address (VA) clone information returned by PssQuerySnapshot. /// /// /// /// PssQuerySnapshot returns a PSS_VA_CLONE_INFORMATION structure when the PSS_QUERY_INFORMATION_CLASS member that the caller /// provides it is PSS_QUERY_VA_CLONE_INFORMATION. /// /// // https://docs.microsoft.com/en-us/previous-versions/windows/desktop/api/processsnapshot/ns-processsnapshot-pss_va_clone_information // typedef struct PSS_VA_CLONE_INFORMATION { HANDLE VaCloneHandle; }; [PInvokeData("processsnapshot.h", MSDNShortId = "F93D61B0-EDB2-4560-A69F-CF839EC98B53")] [StructLayout(LayoutKind.Sequential)] public struct PSS_VA_CLONE_INFORMATION { /// /// A handle to the VA clone process. /// public IntPtr VaCloneHandle; } /// /// Holds the MEMORY_BASIC_INFORMATION returned by PssWalkSnapshot for a virtual address (VA) region. /// /// /// /// PssWalkSnapshot returns a PSS_VA_SPACE_ENTRY structure when the PSS_WALK_INFORMATION_CLASS member that the caller provides /// it is PSS_WALK_VA_SPACE. /// /// // https://docs.microsoft.com/en-us/previous-versions/windows/desktop/api/processsnapshot/ns-processsnapshot-pss_va_space_entry // typedef struct PSS_VA_SPACE_ENTRY { void *BaseAddress; void *AllocationBase; DWORD AllocationProtect; ULONG_PTR RegionSize; DWORD // State; DWORD Protect; DWORD Type; DWORD TimeDateStamp; DWORD SizeOfImage; void *ImageBase; DWORD CheckSum; WORD // MappedFileNameLength; wchar_t const *MappedFileName; }; [PInvokeData("processsnapshot.h", MSDNShortId = "69B8F6A3-76DF-421B-B89B-73BA3254F897")] [StructLayout(LayoutKind.Sequential)] public struct PSS_VA_SPACE_ENTRY { /// /// Information about the VA region. For more information, see MEMORY_BASIC_INFORMATION. /// public IntPtr BaseAddress; /// /// Information about the VA region. For more information, see MEMORY_BASIC_INFORMATION. /// public IntPtr AllocationBase; /// /// Information about the VA region. For more information, see MEMORY_BASIC_INFORMATION. /// public uint AllocationProtect; /// /// Information about the VA region. For more information, see MEMORY_BASIC_INFORMATION. /// public UIntPtr RegionSize; /// /// Information about the VA region. For more information, see MEMORY_BASIC_INFORMATION. /// public uint State; /// /// Information about the VA region. For more information, see MEMORY_BASIC_INFORMATION. /// public uint Protect; /// /// Information about the VA region. For more information, see MEMORY_BASIC_INFORMATION. /// public uint Type; /// /// /// If section information was captured and the region is an executable image ( MEM_IMAGE), this is the /// TimeDateStamp value from the Portable Executable (PE) header which describes the image. It is the low 32 bits of the /// number of seconds since 00:00 January 1, 1970 (a C run-time time_t value), that indicates when the file was created. /// /// public uint TimeDateStamp; /// /// /// If section information was captured and the region is an executable image ( MEM_IMAGE), this is the SizeOfImage /// value from the Portable Executable (PE) header which describes the image. It is the size (in bytes) of the image, including /// all headers, as the image is loaded in memory. /// /// public uint SizeOfImage; /// /// /// If section information was captured and the region is an executable image ( MEM_IMAGE), this is the ImageBase /// value from the Portable Executable (PE) header which describes the image. It is the preferred address of the first byte of /// the image when loaded into memory. /// /// public IntPtr ImageBase; /// /// /// If section information was captured and the region is an executable image ( MEM_IMAGE), this is the CheckSum /// value from the Portable Executable (PE) header which describes the image. It is the image file checksum. /// /// public uint CheckSum; /// /// The length of the mapped file name buffer, in bytes. /// public ushort MappedFileNameLength; /// /// /// If section information was captured, this is the file path backing the section (if any). The path may be in NT namespace. The /// string may not be terminated by a NULL character. The pointer is valid for the lifetime of the walk marker passed to PssWalkSnapshot. /// /// public IntPtr MappedFileName; } /// /// Holds virtual address (VA) space information returned by PssQuerySnapshot. /// /// /// /// PssQuerySnapshot returns a PSS_VA_SPACE_INFORMATION structure when the PSS_QUERY_INFORMATION_CLASS member that the caller /// provides it is PSS_QUERY_VA_SPACE_INFORMATION. /// /// // https://docs.microsoft.com/en-us/previous-versions/windows/desktop/api/processsnapshot/ns-processsnapshot-pss_va_space_information // typedef struct PSS_VA_SPACE_INFORMATION { DWORD RegionCount; }; [PInvokeData("processsnapshot.h", MSDNShortId = "F38FF7EB-DDC5-4692-8F57-8D633193D891")] [StructLayout(LayoutKind.Sequential)] public struct PSS_VA_SPACE_INFORMATION { /// /// The count of VA regions captured. /// public uint RegionCount; } /// Provides a for that is disposed using . public class SafeHPSS : SafeHANDLE { internal HPROCESS ProcessHandle; /// Initializes a new instance of the class and assigns an existing handle. /// An object that represents the pre-existing handle to use. /// /// to reliably release the handle during the finalization phase; otherwise, (not recommended). /// public SafeHPSS(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { } /// Initializes a new instance of the class. private SafeHPSS() : base() { } /// Performs an implicit conversion from to . /// The safe handle instance. /// The result of the conversion. public static implicit operator HPSS(SafeHPSS h) => h.handle; /// protected override bool InternalReleaseHandle() => PssFreeSnapshot(ProcessHandle, handle).Succeeded; } /// Provides a for that is disposed using . public class SafeHPSSWALK : SafeHANDLE { /// Initializes a new instance of the class and assigns an existing handle. /// An object that represents the pre-existing handle to use. /// /// to reliably release the handle during the finalization phase; otherwise, (not recommended). /// public SafeHPSSWALK(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { } /// Initializes a new instance of the class. private SafeHPSSWALK() : base() { } /// Performs an implicit conversion from to . /// The safe handle instance. /// The result of the conversion. public static implicit operator HPSSWALK(SafeHPSSWALK h) => h.handle; /// protected override bool InternalReleaseHandle() => PssWalkMarkerFree(handle).Succeeded; } } }