// Copyright 2024 sjackson0109 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. using System.Runtime.InteropServices; namespace RDPWrap.Common; /// /// All P/Invoke declarations used across RDPWInst, RDPConf and RDPCheck. /// Mirrors the unhooked Win32 imports from the original Delphi sources. /// internal static class NativeMethods { // ─── DLL names ──────────────────────────────────────────────────────────── internal const string Kernel32 = "kernel32.dll"; internal const string Advapi32 = "advapi32.dll"; internal const string WinSta = "winsta.dll"; // ─── Constants ──────────────────────────────────────────────────────────── // Architecture internal const ushort PROCESSOR_ARCHITECTURE_INTEL = 0; internal const ushort PROCESSOR_ARCHITECTURE_IA64 = 6; internal const ushort PROCESSOR_ARCHITECTURE_AMD64 = 9; // Registry internal const uint KEY_WOW64_64KEY = 0x0100; internal const uint KEY_WOW64_32KEY = 0x0200; internal const uint KEY_READ = 0x20019; internal const uint KEY_WRITE = 0x20006; internal const uint KEY_QUERY_VALUE = 0x0001; internal const uint KEY_SET_VALUE = 0x0002; // Service control manager internal const uint SC_MANAGER_CONNECT = 0x0001; internal const uint SC_MANAGER_CREATE_SERVICE = 0x0002; internal const uint SC_MANAGER_ENUMERATE_SERVICE = 0x0004; internal const uint SC_MANAGER_ALL_ACCESS = 0xF003F; internal const uint SERVICE_QUERY_CONFIG = 0x0001; internal const uint SERVICE_CHANGE_CONFIG = 0x0002; internal const uint SERVICE_QUERY_STATUS = 0x0004; internal const uint SERVICE_START = 0x0010; internal const uint SERVICE_STOP = 0x0020; internal const uint SERVICE_ALL_ACCESS = 0xF01FF; internal const uint SERVICE_WIN32 = 0x30; internal const uint SERVICE_STATE_ALL = 0x03; internal const uint SERVICE_NO_CHANGE = 0xFFFFFFFF; internal const uint SERVICE_AUTO_START = 0x02; internal const uint SERVICE_DEMAND_START = 0x03; internal const uint SERVICE_DISABLED = 0x04; internal const uint SERVICE_STOPPED = 0x00000001; internal const uint SERVICE_START_PENDING = 0x00000002; internal const uint SERVICE_STOP_PENDING = 0x00000003; internal const uint SERVICE_RUNNING = 0x00000004; internal const uint SERVICE_CONTINUE_PENDING = 0x00000005; internal const uint SERVICE_PAUSE_PENDING = 0x00000006; internal const uint SERVICE_PAUSED = 0x00000007; internal const uint SC_ENUM_PROCESS_INFO = 0; internal const uint SC_STATUS_PROCESS_INFO = 0; internal const uint ERROR_MORE_DATA = 234; internal const uint ERROR_SERVICE_DOES_NOT_EXIST = 1060; internal const uint ERROR_SERVICE_NOT_ACTIVE = 1062; // Process/Thread internal const uint PROCESS_TERMINATE = 0x0001; internal const uint THREAD_SUSPEND_RESUME = 0x0002; internal const uint TH32CS_SNAPTHREAD = 0x00000004; // Token privileges internal const uint TOKEN_ADJUST_PRIVILEGES = 0x0020; internal const uint TOKEN_QUERY = 0x0008; internal const uint SE_PRIVILEGE_ENABLED = 0x00000002; // Privilege names internal const string SE_DEBUG_NAME = "SeDebugPrivilege"; internal const string SE_RESTORE_NAME = "SeRestorePrivilege"; internal const string SE_BACKUP_NAME = "SeBackupPrivilege"; // Security internal const uint DACL_SECURITY_INFORMATION = 0x00000004; internal const uint SE_FILE_OBJECT = 1; internal const uint GRANT_ACCESS = 1; internal const uint SUB_CONTAINERS_AND_OBJECTS_INHERIT = 0x3; internal const uint NO_MULTIPLE_TRUSTEE = 0; internal const uint TRUSTEE_IS_SID = 0; internal const uint TRUSTEE_IS_WELL_KNOWN_GROUP = 5; internal const uint GENERIC_ALL = 0x10000000; // LoadLibraryEx flags internal const uint LOAD_LIBRARY_AS_DATAFILE = 0x00000002; // Version resource type internal const uint RT_VERSION = 16; // CreateProcess - STARTUPINFO flags internal const uint STARTF_USESHOWWINDOW = 0x00000001; internal const ushort SW_HIDE = 0; // GetModuleHandleEx internal const uint GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS = 0x00000004; internal const uint GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT = 0x00000002; // Error codes internal const uint ERROR_SUCCESS = 0; internal const uint ERROR_ACCESS_DENIED = 5; internal const uint ERROR_NOT_SUPPORTED = 50; internal const uint ERROR_SERVICE_ALREADY_RUNNING = 1056; // ─── Structures ─────────────────────────────────────────────────────────── [StructLayout(LayoutKind.Sequential)] internal struct SYSTEM_INFO { internal ushort wProcessorArchitecture; internal ushort wReserved; internal uint dwPageSize; internal IntPtr lpMinimumApplicationAddress; internal IntPtr lpMaximumApplicationAddress; internal UIntPtr dwActiveProcessorMask; internal uint dwNumberOfProcessors; internal uint dwProcessorType; internal uint dwAllocationGranularity; internal ushort wProcessorLevel; internal ushort wProcessorRevision; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] internal struct STARTUPINFO { internal uint cb; internal string? lpReserved; internal string? lpDesktop; internal string? lpTitle; internal uint dwX, dwY, dwXSize, dwYSize, dwXCountChars, dwYCountChars; internal uint dwFillAttribute; internal uint dwFlags; internal ushort wShowWindow; internal ushort cbReserved2; internal IntPtr lpReserved2; internal IntPtr hStdInput, hStdOutput, hStdError; } [StructLayout(LayoutKind.Sequential)] internal struct PROCESS_INFORMATION { internal IntPtr hProcess; internal IntPtr hThread; internal uint dwProcessId; internal uint dwThreadId; } [StructLayout(LayoutKind.Sequential)] internal struct THREADENTRY32 { internal uint dwSize; internal uint cntUsage; internal uint th32ThreadID; internal uint th32OwnerProcessID; internal int tpBasePri; internal int tpDeltaPri; internal uint dwFlags; } [StructLayout(LayoutKind.Sequential)] internal struct SERVICE_STATUS_PROCESS { internal uint dwServiceType; internal uint dwCurrentState; internal uint dwControlsAccepted; internal uint dwWin32ExitCode; internal uint dwServiceSpecificExitCode; internal uint dwCheckPoint; internal uint dwWaitHint; internal uint dwProcessId; internal uint dwServiceFlags; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] internal struct ENUM_SERVICE_STATUS_PROCESS { internal string lpServiceName; internal string lpDisplayName; internal SERVICE_STATUS_PROCESS ServiceStatusProcess; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] internal struct QUERY_SERVICE_CONFIG { internal uint dwServiceType; internal uint dwStartType; internal uint dwErrorControl; internal string lpBinaryPathName; internal string lpLoadOrderGroup; internal uint dwTagId; internal string lpDependencies; internal string lpServiceStartName; internal string lpDisplayName; } [StructLayout(LayoutKind.Sequential)] internal struct LUID { internal uint LowPart; internal int HighPart; } [StructLayout(LayoutKind.Sequential)] internal struct LUID_AND_ATTRIBUTES { internal LUID Luid; internal uint Attributes; } [StructLayout(LayoutKind.Sequential)] internal struct TOKEN_PRIVILEGES { internal uint PrivilegeCount; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] internal LUID_AND_ATTRIBUTES[] Privileges; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] internal struct EXPLICIT_ACCESS { internal uint grfAccessPermissions; internal uint grfAccessMode; internal uint grfInheritance; internal TRUSTEE Trustee; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] internal struct TRUSTEE { internal IntPtr pMultipleTrustee; internal uint MultipleTrusteeOperation; internal uint TrusteeForm; internal uint TrusteeType; internal IntPtr ptstrName; // SID pointer or string pointer } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] internal struct WTS_SESSION_INFO { internal uint SessionId; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 34)] internal string Name; internal uint State; } // ─── kernel32.dll ───────────────────────────────────────────────────────── [DllImport(Kernel32, SetLastError = true)] internal static extern void GetNativeSystemInfo(out SYSTEM_INFO lpSystemInfo); [DllImport(Kernel32, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool Wow64DisableWow64FsRedirection(out IntPtr oldValue); [DllImport(Kernel32, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool Wow64RevertWow64FsRedirection(IntPtr oldValue); [DllImport(Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] internal static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hFile, uint dwFlags); [DllImport(Kernel32, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool FreeLibrary(IntPtr hModule); [DllImport(Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] internal static extern IntPtr FindResource(IntPtr hModule, IntPtr lpName, IntPtr lpType); [DllImport(Kernel32, SetLastError = true)] internal static extern IntPtr LoadResource(IntPtr hModule, IntPtr hResInfo); [DllImport(Kernel32, SetLastError = true)] internal static extern IntPtr LockResource(IntPtr hResData); [DllImport(Kernel32, SetLastError = true)] internal static extern uint SizeofResource(IntPtr hModule, IntPtr hResInfo); [DllImport(Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool CreateProcess( string? lpApplicationName, string lpCommandLine, IntPtr lpProcessAttributes, IntPtr lpThreadAttributes, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandles, uint dwCreationFlags, IntPtr lpEnvironment, string? lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation); [DllImport(Kernel32, SetLastError = true)] internal static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds); [DllImport(Kernel32, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool CloseHandle(IntPtr hObject); [DllImport(Kernel32, SetLastError = true)] internal static extern IntPtr OpenProcess(uint dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, uint dwProcessId); [DllImport(Kernel32, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool TerminateProcess(IntPtr hProcess, uint uExitCode); [DllImport(Kernel32, SetLastError = true)] internal static extern uint GetCurrentProcessId(); [DllImport(Kernel32, SetLastError = true)] internal static extern uint GetCurrentThreadId(); [DllImport(Kernel32, SetLastError = true)] internal static extern IntPtr CreateToolhelp32Snapshot(uint dwFlags, uint th32ProcessID); [DllImport(Kernel32, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool Thread32First(IntPtr hSnapshot, ref THREADENTRY32 lpte); [DllImport(Kernel32, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool Thread32Next(IntPtr hSnapshot, ref THREADENTRY32 lpte); [DllImport(Kernel32, SetLastError = true)] internal static extern IntPtr OpenThread(uint dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, uint dwThreadId); [DllImport(Kernel32, SetLastError = true)] internal static extern uint SuspendThread(IntPtr hThread); [DllImport(Kernel32, SetLastError = true)] internal static extern uint ResumeThread(IntPtr hThread); [DllImport(Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] internal static extern uint GetModuleFileName(IntPtr hModule, System.Text.StringBuilder lpFilename, uint nSize); [DllImport(Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool GetModuleHandleEx(uint dwFlags, IntPtr lpModuleName, out IntPtr phModule); [DllImport(Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] internal static extern uint ExpandEnvironmentStrings(string lpSrc, System.Text.StringBuilder lpDst, uint nSize); [DllImport(Kernel32, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool DeleteFile(string lpFileName); [DllImport(Kernel32, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool RemoveDirectory(string lpPathName); [DllImport(Kernel32, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool OpenProcessToken(IntPtr processHandle, uint desiredAccess, out IntPtr tokenHandle); // ─── advapi32.dll ───────────────────────────────────────────────────────── [DllImport(Advapi32, SetLastError = true)] internal static extern IntPtr OpenSCManager(string? lpMachineName, string? lpDatabaseName, uint dwDesiredAccess); [DllImport(Advapi32, CharSet = CharSet.Unicode, SetLastError = true)] internal static extern IntPtr OpenService(IntPtr hSCManager, string lpServiceName, uint dwDesiredAccess); [DllImport(Advapi32, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool CloseServiceHandle(IntPtr hSCObject); [DllImport(Advapi32, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool QueryServiceConfig(IntPtr hService, IntPtr lpServiceConfig, uint cbBufSize, out uint pcbBytesNeeded); [DllImport(Advapi32, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool QueryServiceStatusEx(IntPtr hService, uint InfoLevel, IntPtr lpBuffer, uint cbBufSize, out uint pcbBytesNeeded); [DllImport(Advapi32, CharSet = CharSet.Unicode, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool ChangeServiceConfig(IntPtr hService, uint dwServiceType, uint dwStartType, uint dwErrorControl, string? lpBinaryPathName, string? lpLoadOrderGroup, IntPtr lpdwTagId, string? lpDependencies, string? lpServiceStartName, string? lpPassword, string? lpDisplayName); [DllImport(Advapi32, CharSet = CharSet.Unicode, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool StartService(IntPtr hService, uint dwNumServiceArgs, string[]? lpServiceArgVectors); [DllImport(Advapi32, CharSet = CharSet.Unicode, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool EnumServicesStatusEx( IntPtr hSCManager, uint InfoLevel, uint dwServiceType, uint dwServiceState, IntPtr lpServices, uint cbBufSize, out uint pcbBytesNeeded, out uint lpServicesReturned, ref uint lpResumeHandle, string? pszGroupName); [DllImport(Advapi32, CharSet = CharSet.Unicode, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool LookupPrivilegeValue(string? lpSystemName, string lpName, out LUID lpLuid); [DllImport(Advapi32, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool AdjustTokenPrivileges(IntPtr tokenHandle, [MarshalAs(UnmanagedType.Bool)] bool disableAllPrivileges, ref TOKEN_PRIVILEGES newState, uint bufferLength, IntPtr previousState, IntPtr returnLength); [DllImport(Advapi32, CharSet = CharSet.Unicode, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool ConvertStringSidToSid(string stringSid, out IntPtr sid); [DllImport(Advapi32, SetLastError = true)] internal static extern uint SetEntriesInAcl(uint cCountOfExplicitEntries, ref EXPLICIT_ACCESS pListOfExplicitEntries, IntPtr oldAcl, out IntPtr newAcl); [DllImport(Advapi32, CharSet = CharSet.Unicode, SetLastError = true)] internal static extern uint SetNamedSecurityInfo(string pObjectName, uint ObjectType, uint SecurityInfo, IntPtr psidOwner, IntPtr psidGroup, IntPtr pDacl, IntPtr pSacl); [DllImport(Advapi32, SetLastError = true)] internal static extern IntPtr LocalFree(IntPtr hMem); // ─── winsta.dll ─────────────────────────────────────────────────────────── /// /// Enumerates WTS sessions on the local server. /// Pass IntPtr.Zero as hServer for the local machine. /// [DllImport(WinSta, EntryPoint = "WinStationEnumerateW", CharSet = CharSet.Unicode, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool WinStationEnumerate(IntPtr hServer, out IntPtr ppSessionInfo, out uint pCount); [DllImport(WinSta, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool WinStationFreeMemory(IntPtr p); }