Check previously-ignored injection / capture / rumble return values

- injector bitness gate: IsWow64Process2 failure was treated as "native", which
  would send the x64 DLL into a 32-bit target. Fall back to the legacy
  IsWow64Process before giving up to permissive.
- injector helper exit: GetExitCodeProcess's BOOL was ignored; on a failed query
  surface GetLastError instead of a misleading exit code.
- window_capture: CreateShaderResourceView's HRESULT was ignored, and width_/
  height_ were committed even on failure, so the (latest_ == nullptr) recreate
  guard never retried -- a silently black mirror until the next resize. Only
  commit the dims on success; otherwise drop latest_ so the next frame retries.
- xinput rumble: make the best-effort XInputSetState ignore explicit (a
  disconnected pad re-syncs on the next refresh; the result isn't actionable).

The GetClientRect/ClientToScreen reads in mkb_forward are left as-is: a failure
there is a single self-correcting frame (the mapping is rejected and reused next
frame), so checking them adds no actionable behavior.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-24 01:43:55 +02:00
parent 12c4fb8a07
commit 1a93fcf196
4 changed files with 28 additions and 14 deletions

View File

@@ -50,7 +50,15 @@ bool is_wow64_process(HANDLE process)
{
return process_machine != IMAGE_FILE_MACHINE_UNKNOWN;
}
return false; // be permissive if the query is unavailable
// IsWow64Process2 failed -- fall back to the legacy query rather than guessing "native", since
// guessing wrong sends the x64 DLL into a 32-bit target (which can't load it). Only if BOTH
// queries fail do we fall back to permissive.
BOOL wow64 = FALSE;
if (IsWow64Process(process, &wow64))
{
return wow64 != FALSE;
}
return false; // both queries failed; best-effort assume native
}
// Replace the trailing file name of `path` with `name` (same directory).
@@ -86,12 +94,13 @@ InjectResult inject_via_helper(unsigned long pid, const std::wstring& dll_path)
}
WaitForSingleObject(pi.hProcess, INFINITE);
DWORD exit_code = 1;
GetExitCodeProcess(pi.hProcess, &exit_code);
const BOOL got = GetExitCodeProcess(pi.hProcess, &exit_code);
const DWORD err = got ? exit_code : GetLastError(); // on a failed query, surface the OS error
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
if (exit_code != 0)
if (!got || exit_code != 0)
{
return InjectResult{InjectStatus::HelperFailed, exit_code};
return InjectResult{InjectStatus::HelperFailed, err};
}
return InjectResult{InjectStatus::Ok, 0};
}