using System.Runtime.InteropServices; namespace SpdUp.Core; /// /// P/Invoke declarations used across the application. /// public static class NativeMethods { // ── Memory management ────────────────────────────────────────────── [DllImport("psapi.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool EmptyWorkingSet(IntPtr hProcess); [DllImport("kernel32.dll", SetLastError = true)] public static extern IntPtr OpenProcess(uint dwDesiredAccess, bool bInheritHandle, int dwProcessId); [DllImport("kernel32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CloseHandle(IntPtr hObject); [DllImport("kernel32.dll", SetLastError = true)] public static extern bool SetProcessWorkingSetSizeEx( IntPtr hProcess, IntPtr dwMinimumWorkingSetSize, IntPtr dwMaximumWorkingSetSize, uint flags); // ── Timer resolution ─────────────────────────────────────────────── [DllImport("ntdll.dll", SetLastError = true)] public static extern int NtSetTimerResolution(uint DesiredResolution, bool SetResolution, out uint CurrentResolution); [DllImport("ntdll.dll", SetLastError = true)] public static extern int NtQueryTimerResolution(out uint MinimumResolution, out uint MaximumResolution, out uint CurrentResolution); // ── System memory info ───────────────────────────────────────────── [StructLayout(LayoutKind.Sequential)] public struct MEMORYSTATUSEX { public uint dwLength; public uint dwMemoryLoad; public ulong ullTotalPhys; public ulong ullAvailPhys; public ulong ullTotalPageFile; public ulong ullAvailPageFile; public ulong ullTotalVirtual; public ulong ullAvailVirtual; public ulong ullAvailExtendedVirtual; } [DllImport("kernel32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool GlobalMemoryStatusEx(ref MEMORYSTATUSEX lpBuffer); // ── System cache / standby list purge ────────────────────────────── public enum SYSTEM_MEMORY_LIST_COMMAND { MemoryCaptureAccessedBits = 0, MemoryCaptureAndResetAccessedBits = 1, MemoryEmptyWorkingSets = 2, MemoryFlushModifiedList = 3, MemoryPurgeStandbyList = 4, MemoryPurgeLowPriorityStandbyList = 5, MemoryCommandMax = 6 } [DllImport("ntdll.dll")] public static extern int NtSetSystemInformation( int SystemInformationClass, ref int SystemInformation, int SystemInformationLength); // SystemMemoryListInformation = 0x0050 public const int SystemMemoryListInformation = 0x0050; // ── Privilege ────────────────────────────────────────────────────── [DllImport("advapi32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool OpenProcessToken(IntPtr ProcessHandle, uint DesiredAccess, out IntPtr TokenHandle); [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool LookupPrivilegeValue(string? lpSystemName, string lpName, out LUID lpLuid); [DllImport("advapi32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool AdjustTokenPrivileges( IntPtr TokenHandle, bool DisableAllPrivileges, ref TOKEN_PRIVILEGES NewState, uint BufferLength, IntPtr PreviousState, IntPtr ReturnLength); [StructLayout(LayoutKind.Sequential)] public struct LUID { public uint LowPart; public int HighPart; } [StructLayout(LayoutKind.Sequential)] public struct LUID_AND_ATTRIBUTES { public LUID Luid; public uint Attributes; } [StructLayout(LayoutKind.Sequential)] public struct TOKEN_PRIVILEGES { public uint PrivilegeCount; public LUID_AND_ATTRIBUTES Privileges; } public const uint TOKEN_ADJUST_PRIVILEGES = 0x0020; public const uint TOKEN_QUERY = 0x0008; public const uint SE_PRIVILEGE_ENABLED = 0x00000002; public const string SE_DEBUG_NAME = "SeDebugPrivilege"; public const string SE_PROF_SINGLE_PROCESS_NAME = "SeProfileSingleProcessPrivilege"; public const string SE_INC_BASE_PRIORITY_NAME = "SeIncreaseBasePriorityPrivilege"; public const uint PROCESS_ALL_ACCESS = 0x001F0FFF; public const uint PROCESS_SET_INFORMATION = 0x0200; public const uint PROCESS_QUERY_INFORMATION = 0x0400; /// /// Enable a privilege on the current process token. /// public static bool EnablePrivilege(string privilege) { try { if (!OpenProcessToken(System.Diagnostics.Process.GetCurrentProcess().Handle, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, out var tokenHandle)) return false; try { if (!LookupPrivilegeValue(null, privilege, out var luid)) return false; var tp = new TOKEN_PRIVILEGES { PrivilegeCount = 1, Privileges = new LUID_AND_ATTRIBUTES { Luid = luid, Attributes = SE_PRIVILEGE_ENABLED } }; return AdjustTokenPrivileges(tokenHandle, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero); } finally { CloseHandle(tokenHandle); } } catch { return false; } } }