diff --git a/WhiteMagic/ExternalReader.cs b/WhiteMagic/ExternalReader.cs
index afc591f..c749f29 100644
--- a/WhiteMagic/ExternalReader.cs
+++ b/WhiteMagic/ExternalReader.cs
@@ -37,10 +37,11 @@ public sealed class ExternalReader : MemoryBase
public ExternalReader(System.Diagnostics.Process process, ProcessAccess desiredAccess = DefaultAccess)
{
_processId = process.Id;
- if ((desiredAccess & ProcessAccess.QueryInformation) == 0)
+ const ProcessAccess queryAccess = ProcessAccess.QueryInformation | ProcessAccess.QueryLimitedInformation;
+ if ((desiredAccess & queryAccess) == 0)
{
throw new ArgumentException(
- "ExternalReader requires ProcessAccess.QueryInformation to determine target bitness.",
+ "ExternalReader requires ProcessAccess.QueryInformation or ProcessAccess.QueryLimitedInformation to determine target bitness.",
nameof(desiredAccess));
}
diff --git a/WhiteMagic/Injection/DllInjector.cs b/WhiteMagic/Injection/DllInjector.cs
index 6458b8e..6d87a26 100644
--- a/WhiteMagic/Injection/DllInjector.cs
+++ b/WhiteMagic/Injection/DllInjector.cs
@@ -215,7 +215,7 @@ public sealed class DllInjector
{
IntPtr result;
- if (Environment.Is64BitProcess)
+ if (_currentIs64Bit)
{
var originalContext = new Context64 { ContextFlags = ContextFlags.Amd64Full };
if (!NativeMethods.GetThreadContext(thread, ref originalContext))
@@ -264,32 +264,23 @@ public sealed class DllInjector
}
else
{
- // 32-bit process on either a 32-bit or 64-bit (WOW64) host.
- bool useWow64 = Environment.Is64BitOperatingSystem;
-
+ // 32-bit process targeting a 32-bit process. The target context is
+ // a native x86 CONTEXT; the WOW64 APIs are for 64-bit callers only.
var originalContext = new Context32 { ContextFlags = ContextFlags.X86Full };
- bool gotContext = useWow64
- ? NativeMethods.Wow64GetThreadContext(thread, ref originalContext)
- : NativeMethods.GetThreadContext(thread, ref originalContext);
- if (!gotContext)
+ if (!NativeMethods.GetThreadContext(thread, ref originalContext))
{
int error = Marshal.GetLastPInvokeError();
- string api = useWow64 ? "Wow64GetThreadContext" : "GetThreadContext";
- throw new InvalidOperationException($"{api} failed (error {error}).");
+ throw new InvalidOperationException($"GetThreadContext failed (error {error}).");
}
var redirectContext = originalContext;
redirectContext.Eip = (uint)(nint)remoteBase;
redirectContext.Esp = (uint)(nint)stackTop;
- bool setContext = useWow64
- ? NativeMethods.Wow64SetThreadContext(thread, ref redirectContext)
- : NativeMethods.SetThreadContext(thread, ref redirectContext);
- if (!setContext)
+ if (!NativeMethods.SetThreadContext(thread, ref redirectContext))
{
int error = Marshal.GetLastPInvokeError();
- string api = useWow64 ? "Wow64SetThreadContext" : "SetThreadContext";
- throw new InvalidOperationException($"{api} failed (error {error}).");
+ throw new InvalidOperationException($"SetThreadContext failed (error {error}).");
}
if (NativeMethods.ResumeThread(thread) == 0xFFFFFFFF)
@@ -306,14 +297,10 @@ public sealed class DllInjector
throw new InvalidOperationException($"SuspendThread failed while capturing result (error {error}).");
}
- bool restoredContext = useWow64
- ? NativeMethods.Wow64SetThreadContext(thread, ref originalContext)
- : NativeMethods.SetThreadContext(thread, ref originalContext);
- if (!restoredContext)
+ if (!NativeMethods.SetThreadContext(thread, ref originalContext))
{
int error = Marshal.GetLastPInvokeError();
- string api = useWow64 ? "Wow64SetThreadContext" : "SetThreadContext";
- throw new InvalidOperationException($"{api} restore failed (error {error}).");
+ throw new InvalidOperationException($"SetThreadContext restore failed (error {error}).");
}
if (NativeMethods.ResumeThread(thread) == 0xFFFFFFFF)
diff --git a/WhiteMagic/Native/NativeMethods.cs b/WhiteMagic/Native/NativeMethods.cs
index 8dbca1e..ab51b08 100644
--- a/WhiteMagic/Native/NativeMethods.cs
+++ b/WhiteMagic/Native/NativeMethods.cs
@@ -152,19 +152,6 @@ internal static partial class NativeMethods
SafeMemoryHandle thread,
ref Context32 context);
- /// Sets a 32-bit (WOW64) thread context.
- [LibraryImport("kernel32.dll", SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- internal static partial bool Wow64SetThreadContext(
- SafeMemoryHandle thread,
- ref Context32 context);
-
- /// Gets a 32-bit (WOW64) thread context.
- [LibraryImport("kernel32.dll", SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- internal static partial bool Wow64GetThreadContext(
- SafeMemoryHandle thread,
- ref Context32 context);
// ── Modules ──────────────────────────────────────────────────────────────
diff --git a/WhiteMagic/Native/NativeStructures.cs b/WhiteMagic/Native/NativeStructures.cs
index 5fef352..1395367 100644
--- a/WhiteMagic/Native/NativeStructures.cs
+++ b/WhiteMagic/Native/NativeStructures.cs
@@ -29,8 +29,8 @@ public unsafe struct FloatingSaveArea32
}
///
-/// A 32-bit (x86/WOW64) thread context. Use it with
-/// Wow64GetThreadContext and Wow64SetThreadContext to inspect a 32-bit thread.
+/// A 32-bit x86 thread context. Use it with GetThreadContext and
+/// SetThreadContext from a 32-bit process targeting a 32-bit thread.
/// The total size is 716 bytes.
///
[StructLayout(LayoutKind.Sequential)]