// File: Services/WinApi.cs using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Text.Json.Serialization; using WebmrAPI.Utils; namespace WebmrAPI.Services { [SupportedOSPlatform("windows")] public static class WinApi { public const uint PROCESS_QUERY_INFORMATION = 0x00000400; public const uint PROCESS_VM_READ = 0x00000010; public const uint PROCESS_VM_OPERATION = 0x00000008; public static int LastError { get => Marshal.GetLastWin32Error(); } public static uint MBISize { get => (uint)Marshal.SizeOf(typeof(MEMORY_BASIC_INFORMATION)); } [JsonConverter(typeof(JsonEnumConverter))] public enum MemoryState : uint { Undefined = 0, Commit = 0x00001000, Reserve = 0x00002000, Free = 0x00010000, } [JsonConverter(typeof(JsonEnumConverter))] public enum MemoryType : uint { Undefined = 0, Image = 0x01000000, Mapped = 0x00040000, Private = 0x00020000, } [JsonConverter(typeof(JsonEnumConverter))] public enum MemoryPageProtectionState : uint { Undefined = 0, NoAccess = 0x0001, ReadOnly = 0x0002, ReadWrite = 0x0004, WriteCopy = 0x0008, Execute = 0x0010, ExecuteRead = 0x0020, ExecuteReadWrite = 0x0040, ExecuteWriteCopy = 0x0080, Guard = 0x0100, NoCache = 0x0200, WriteCombine = 0x0400, } // --- P/Invoke Declarations --- // https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-memory_basic_information [StructLayout(LayoutKind.Sequential)] public struct MEMORY_BASIC_INFORMATION { public IntPtr BaseAddress; public IntPtr AllocationBase; public uint AllocationProtect; public ushort PartitionId; public UIntPtr RegionSize; public MemoryState State; public MemoryPageProtectionState PageProtection; public MemoryType Type; } // https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-openprocess [DllImport("kernel32.dll", SetLastError = true)] public static extern IntPtr OpenProcess( uint dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, uint dwProcessId ); // https://learn.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-closehandle [DllImport("kernel32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CloseHandle(IntPtr hObject); // https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-virtualqueryex [DllImport("kernel32.dll", SetLastError = true)] public static extern int VirtualQueryEx( IntPtr hProcess, IntPtr lpAddress, out MEMORY_BASIC_INFORMATION lpBuffer, uint dwLength ); // --- Module-related P/Invokes (from psapi.dll and kernel32.dll) --- // https://learn.microsoft.com/en-us/windows/win32/api/psapi/nf-psapi-enumprocessmodulesex [DllImport("psapi.dll", SetLastError = true)] public static extern bool EnumProcessModulesEx( IntPtr hProcess, [Out] IntPtr[] lphModule, // Array to receive module handles uint cb, // Size of the lphModule array, in bytes out uint lpcbNeeded, // Number of bytes required to store all module handles uint dwFilterFlag // Filter for modules (e.g., LIST_MODULES_ALL) ); // https://learn.microsoft.com/en-us/windows/win32/api/psapi/nf-psapi-getmodulefilenameexw [DllImport("psapi.dll", SetLastError = true, CharSet = CharSet.Unicode)] public static extern uint GetModuleFileNameEx( IntPtr hProcess, IntPtr hModule, [Out] System.Text.StringBuilder lpFilename, uint nSize ); // https://learn.microsoft.com/en-us/windows/win32/api/psapi/nf-psapi-getmodulebasenamew [DllImport("psapi.dll", SetLastError = true, CharSet = CharSet.Unicode)] public static extern uint GetModuleBaseName( IntPtr hProcess, IntPtr hModule, [Out] System.Text.StringBuilder lpBaseName, uint nSize ); // https://learn.microsoft.com/en-us/windows/win32/api/psapi/ns-psapi-_moduleinfo [StructLayout(LayoutKind.Sequential)] public struct MODULEINFO { public IntPtr lpBaseOfDll; public uint SizeOfImage; public IntPtr EntryPoint; } // https://learn.microsoft.com/en-us/windows/win32/api/psapi/nf-psapi-getmoduleinformation [DllImport("psapi.dll", SetLastError = true)] public static extern bool GetModuleInformation( IntPtr hProcess, IntPtr hModule, out MODULEINFO lpmodinfo, uint cb ); // --- Thread-related P/Invokes (from kernel32.dll and ntdll.dll) --- // https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-openthread [DllImport("kernel32.dll", SetLastError = true)] public static extern IntPtr OpenThread( uint dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, uint dwThreadId ); // https://learn.microsoft.com/en-us/windows/win32/api/winternl/nf-winternl-ntqueryinformationthread [DllImport("ntdll.dll", SetLastError = true)] public static extern int NtQueryInformationThread( IntPtr ThreadHandle, THREAD_INFO_CLASS ThreadInformationClass, IntPtr ThreadInformation, // Pointer to buffer uint ThreadInformationLength, out uint ReturnLength ); // Enum for ThreadInformationClass in NtQueryInformationThread // https://ntdoc.m417z.com/threadinfoclass public enum THREAD_INFO_CLASS : int { ThreadBasicInformation, // q: THREAD_BASIC_INFORMATION ThreadTimes, // q: KERNEL_USER_TIMES ThreadPriority, // s: KPRIORITY (requires SeIncreaseBasePriorityPrivilege) ThreadBasePriority, // s: KPRIORITY ThreadAffinityMask, // s: KAFFINITY ThreadImpersonationToken, // s: HANDLE ThreadDescriptorTableEntry, // q: DESCRIPTOR_TABLE_ENTRY (or WOW64_DESCRIPTOR_TABLE_ENTRY) ThreadEnableAlignmentFaultFixup, // s: BOOLEAN ThreadEventPair, // Obsolete ThreadQuerySetWin32StartAddress, // qs: PVOID (requires THREAD_Set_LIMITED_INFORMATION) ThreadZeroTlsCell, // s: ULONG // TlsIndex // 10 ThreadPerformanceCount, // q: LARGE_INTEGER ThreadAmILastThread, // q: ULONG ThreadIdealProcessor, // s: ULONG ThreadPriorityBoost, // qs: ULONG ThreadSetTlsArrayAddress, // s: ULONG_PTR ThreadIsIoPending, // q: ULONG ThreadHideFromDebugger, // q: BOOLEAN; s: void ThreadBreakOnTermination, // qs: ULONG ThreadSwitchLegacyState, // s: void // NtCurrentThread // NPX/FPU ThreadIsTerminated, // q: ULONG // 20 ThreadLastSystemCall, // q: THREAD_LAST_SYSCALL_INFORMATION ThreadIoPriority, // qs: IO_PRIORITY_HINT (requires SeIncreaseBasePriorityPrivilege) ThreadCycleTime, // q: THREAD_CYCLE_TIME_INFORMATION (requires THREAD_QUERY_LIMITED_INFORMATION) ThreadPagePriority, // qs: PAGE_PRIORITY_INFORMATION ThreadActualBasePriority, // s: LONG (requires SeIncreaseBasePriorityPrivilege) ThreadTebInformation, // q: THREAD_TEB_INFORMATION (requires THREAD_GET_CONTEXT + THREAD_SET_CONTEXT) ThreadCSwitchMon, // Obsolete ThreadCSwitchPmu, // Obsolete ThreadWow64Context, // qs: WOW64_CONTEXT, ARM_NT_CONTEXT since 20H1 ThreadGroupInformation, // qs: GROUP_AFFINITY // 30 ThreadUmsInformation, // q: THREAD_UMS_INFORMATION // Obsolete ThreadCounterProfiling, // q: BOOLEAN; s: THREAD_PROFILING_INFORMATION? ThreadIdealProcessorEx, // qs: PROCESSOR_NUMBER; s: previous PROCESSOR_NUMBER on return ThreadCpuAccountingInformation, // q: BOOLEAN; s: HANDLE (NtOpenSession) // NtCurrentThread // since WIN8 ThreadSuspendCount, // q: ULONG // since WINBLUE ThreadHeterogeneousCpuPolicy, // q: KHETERO_CPU_POLICY // since THRESHOLD ThreadContainerId, // q: GUID ThreadNameInformation, // qs: THREAD_NAME_INFORMATION (requires THREAD_SET_LIMITED_INFORMATION) ThreadSelectedCpuSets, // q: ULONG[] ThreadSystemThreadInformation, // q: SYSTEM_THREAD_INFORMATION // 40 ThreadActualGroupAffinity, // q: GROUP_AFFINITY // since THRESHOLD2 ThreadDynamicCodePolicyInfo, // q: ULONG; s: ULONG (NtCurrentThread) ThreadExplicitCaseSensitivity, // qs: ULONG; s: 0 disables, otherwise enables // (requires SeDebugPrivilege and PsProtectedSignerAntimalware) ThreadWorkOnBehalfTicket, // ALPC_WORK_ON_BEHALF_TICKET // RTL_WORK_ON_BEHALF_TICKET_EX // NtCurrentThread ThreadSubsystemInformation, // q: SUBSYSTEM_INFORMATION_TYPE // since REDSTONE2 ThreadDbgkWerReportActive, // s: ULONG; s: 0 disables, otherwise enables ThreadAttachContainer, // s: HANDLE (job object) // NtCurrentThread ThreadManageWritesToExecutableMemory, // MANAGE_WRITES_TO_EXECUTABLE_MEMORY // since REDSTONE3 ThreadPowerThrottlingState, // qs: POWER_THROTTLING_THREAD_STATE // since REDSTONE3 (set), WIN11 22H2 (query) ThreadWorkloadClass, // THREAD_WORKLOAD_CLASS // since REDSTONE5 // 50 ThreadCreateStateChange, // since WIN11 ThreadApplyStateChange, ThreadStrongerBadHandleChecks, // s: ULONG // NtCurrentThread // since 22H1 ThreadEffectiveIoPriority, // q: IO_PRIORITY_HINT ThreadEffectivePagePriority, // q: ULONG ThreadUpdateLockOwnership, // THREAD_LOCK_OWNERSHIP // since 24H2 ThreadSchedulerSharedDataSlot, // SCHEDULER_SHARED_DATA_SLOT_INFORMATION ThreadTebInformationAtomic, // q: THREAD_TEB_INFORMATION (requires THREAD_GET_CONTEXT + THREAD_QUERY_INFORMATION) ThreadIndexInformation, // THREAD_INDEX_INFORMATION MaxThreadInfoClass } // Structure for ThreadBasicInformation (if needed, though ThreadQuerySetWin32StartAddress directly gives address) // https://ntdoc.m417z.com/thread_basic_information [StructLayout(LayoutKind.Sequential)] public struct THREAD_BASIC_INFORMATION { public int ExitStatus; public IntPtr TebBaseAddress; public CLIENT_ID ClientId; public IntPtr AffinityMask; public int Priority; public int BasePriority; } // https://ntdoc.m417z.com/client_id [StructLayout(LayoutKind.Sequential)] public struct CLIENT_ID { public IntPtr UniqueProcess; public IntPtr UniqueThread; } } }