Files
whitemagic/WhiteMagic/Native/SystemMethods.cs
kbe c40f3fd791 Fix InputSimulator wParam, PeHeaderParser double-parse, and other review issues
Bug fixes:
- InputSimulator: Pass correct button state (MK_LBUTTON/MK_RBUTTON) in wParam for button-down messages instead of 0.
- PeHeaderParser: ParseOptionalHeader now reads only the optional header, not section headers (fixes double-parse waste).
- EntryPoint: Removed useless isPe32Plus branch (AddressOfEntryPoint is at offset 16 in both PE32 and PE32+).
- RemoteWindow: Handle null foreground window case in Activate to avoid calling GetWindowThreadProcessId with HWND 0.
- RemotePointer: Remove dead null-conditional operators (encoding ??) since encoding is non-nullable.

Constants added:
- SystemMethods: MkLButton (0x0001) and MkRButton (0x0002) for mouse button state flags.

Tests: 199 passing, 4 integration/interactive skipped.
2026-07-22 01:28:42 +02:00

183 lines
6.7 KiB
C#

using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace WhiteMagic.Native;
/// <summary>
/// P/Invoke declarations for kernel32/ntdll/user32 APIs used by the high-level
/// PEB, TEB, windowing, and input helpers. These live in a separate partial file so
/// they can evolve independently of <see cref="NativeMethods"/>.
/// </summary>
internal static partial class NativeMethods
{
// ── Natives used directly by public helpers ──────────────────────────────
/// <summary>Queries information about the specified process.</summary>
[LibraryImport("ntdll.dll")]
internal static partial int NtQueryInformationProcess(
SafeMemoryHandle processHandle,
int processInformationClass,
ref ProcessBasicInformation processInformation,
uint processInformationLength,
out uint returnLength);
/// <summary>Queries information about the specified thread.</summary>
[LibraryImport("ntdll.dll")]
internal static partial int NtQueryInformationThread(
SafeMemoryHandle threadHandle,
int threadInformationClass,
ref ThreadBasicInformation threadInformation,
uint threadInformationLength,
out uint returnLength);
/// <summary>Enumerates all top-level windows on the screen.</summary>
[LibraryImport("user32.dll", SetLastError = true)]
internal static partial int EnumWindows(
nint lpEnumFunc,
IntPtr lParam);
/// <summary>Retrieves the identifier of the thread that created the window and the process id of the window.</summary>
[LibraryImport("user32.dll", SetLastError = true)]
internal static partial uint GetWindowThreadProcessId(
IntPtr hWnd,
out uint lpdwProcessId);
/// <summary>Retrieves the name of the class to which the specified window belongs.</summary>
[LibraryImport("user32.dll", SetLastError = true, StringMarshalling = StringMarshalling.Utf16)]
internal static partial int GetClassNameW(
IntPtr hWnd,
[Out] char[] lpClassName,
int nMaxCount);
/// <summary>Copies the text of the specified window's title bar into a buffer.</summary>
[LibraryImport("user32.dll", SetLastError = true, StringMarshalling = StringMarshalling.Utf16)]
internal static partial int GetWindowTextW(
IntPtr hWnd,
[Out] char[] lpString,
int nMaxCount);
/// <summary>Changes the text of the specified window's title bar.</summary>
[LibraryImport("user32.dll", SetLastError = true, StringMarshalling = StringMarshalling.Utf16)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static partial bool SetWindowTextW(
IntPtr hWnd,
string lpString);
/// <summary>Changes the size, position, and Z order of a child, pop-up, or top-level window.</summary>
[LibraryImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static partial bool SetWindowPos(
IntPtr hWnd,
IntPtr hWndInsertAfter,
int x,
int y,
int cx,
int cy,
uint uFlags);
/// <summary>Retrieves a handle to the foreground window.</summary>
[LibraryImport("user32.dll", SetLastError = true)]
internal static partial IntPtr GetForegroundWindow();
/// <summary>Brings the thread that created the specified window into the foreground and activates the window.</summary>
[LibraryImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static partial bool SetForegroundWindow(IntPtr hWnd);
/// <summary>Flashes the specified window.</summary>
[LibraryImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static partial bool FlashWindowEx(ref FlashWindowInfo pwfi);
/// <summary>Attaches or detaches the input processing mechanism of one thread to that of another thread.</summary>
[LibraryImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static partial bool AttachThreadInput(
uint idAttach,
uint idAttachTo,
[MarshalAs(UnmanagedType.Bool)] bool fAttach);
/// <summary>Places a message in the message queue associated with the thread that created the specified window.</summary>
[LibraryImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static partial bool PostMessageW(
IntPtr hWnd,
uint msg,
nuint wParam,
nint lParam);
// ── Window / input constants ───────────────────────────────────────────────
internal const uint WmChar = 0x0102;
internal const uint WmLButtonDown = 0x0201;
internal const uint WmLButtonUp = 0x0202;
internal const uint WmRButtonDown = 0x0204;
internal const uint WmRButtonUp = 0x0205;
// Mouse button state flags for WM_*BUTTONDOWN messages
internal const uint MkLButton = 0x0001;
internal const uint MkRButton = 0x0002;
internal static readonly IntPtr HwndTop = IntPtr.Zero;
internal const uint SwpShowWindow = 0x0040;
internal const uint SwpNoActivate = 0x0010;
internal const uint FlashwAll = 0x00000003;
internal const uint FlashwCaption = 0x00000001;
internal const uint FlashwTray = 0x00000002;
internal const uint FlashwTimer = 0x00000004;
internal const uint FlashwTimerNoFg = 0x0000000C;
}
/// <summary>
/// Layout matches <c>PROCESS_BASIC_INFORMATION</c> (ProcessBasicInformation = 0).
/// </summary>
[StructLayout(LayoutKind.Sequential)]
internal struct ProcessBasicInformation
{
public int ExitStatus;
public IntPtr PebBaseAddress;
public UIntPtr AffinityMask;
public int BasePriority;
public UIntPtr UniqueProcessId;
public UIntPtr InheritedFromUniqueProcessId;
}
/// <summary>
/// Layout matches <c>THREAD_BASIC_INFORMATION</c> (ThreadBasicInformation = 0).
/// </summary>
[StructLayout(LayoutKind.Sequential)]
internal struct ThreadBasicInformation
{
public int ExitStatus;
public IntPtr TebBaseAddress;
public ClientId ClientId;
public UIntPtr AffinityMask;
public int Priority;
public int BasePriority;
}
/// <summary>
/// Layout matches <c>CLIENT_ID</c>.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
internal struct ClientId
{
public IntPtr UniqueProcess;
public IntPtr UniqueThread;
}
/// <summary>
/// Layout matches <c>FLASHWINFO</c> used by <see cref="NativeMethods.FlashWindowEx"/>.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
internal struct FlashWindowInfo
{
public uint cbSize;
public IntPtr hwnd;
public uint dwFlags;
public uint uCount;
public uint dwTimeout;
}