andrewmd5/Borderless-Gaming · warning · Win32Exception
Win32Exception
Error message
Win32Exception
What it means
IsProcessElevated throws a Win32Exception when the native OpenProcessToken call fails to open the current process's access token with TOKEN_QUERY access. Win32Exception wraps the last Win32 error code (Marshal.GetLastWin32Error). OpenProcessToken can fail for the current process only in rare conditions such as a corrupted/security-hardened environment, an invalid process handle, or security software blocking token access.
Solutions
- Check the Win32Exception.NativeErrorCode for the real failure cause and fix accordingly (e.g. ERROR_ACCESS_DENIED).
- Prefer Uac.Elevated (or wrap IsElevated in try/catch) which already swallows this exception and returns false.
- Retry once if the call races with process startup/shutdown, since GetCurrentProcess().Handle should always be openable.
- If security software blocks token inspection, fall back to Uac.IsRunAsAdmin() (WindowsPrincipal/WindowsBuiltInRole.Administrator) as a heuristic elevation check.
Example fix
// before
return Uac.IsProcessElevated();
// after
bool elevated;
try { elevated = Uac.IsProcessElevated(); }
catch (Win32Exception ex) {
Trace.WriteLine($"OpenProcessToken failed: {ex.NativeErrorCode}");
elevated = Uac.IsRunAsAdmin(); // fallback heuristic
} Defensive patterns
Strategy: try-catch
Validate before calling
// No reliable pre-check: token open for the own process normally always succeeds.
// Guard by checking OS support first:
if (Environment.OSVersion.Version.Major < 6) return; // path never reached
if (!Environment.IsPrivilegedProcess.HasValue) { /* .NET: Environment just probe */ } Type guard
static bool CanQueryToken()
{
try
{
using var p = System.Diagnostics.Process.GetCurrentProcess();
return p.Handle != IntPtr.Zero;
}
catch { return false; }
} Try / catch
try
{
bool elevated = Uac.IsElevated();
}
catch (System.ComponentModel.Win32Exception ex)
{
Log.Warn($"Token query failed (code {ex.NativeErrorCode}); assuming non-elevated.");
bool elevated = false;
} Prevention
- Use the Uac.Elevated property instead of IsProcessElevated — it already swallows Win32Exception.
- Log Win32Exception.NativeErrorCode to identify the true native failure cause.
- Fall back to Uac.IsRunAsAdmin() when native token queries fail.
- Do not call elevation checks during process shutdown races.
When it happens
Trigger: Calling Uac.IsElevated()/Uac.IsProcessElevated() when OpenProcessToken(Process.GetCurrentProcess().Handle, TOKEN_QUERY, out hToken) returns false — e.g. the process handle is invalid (racing process exit), or the security context/AV policy denies opening the own process token.
Common situations: Running under aggressive security/EDR software that hooks advapi32 token APIs; calling the API from an unusual host (service, sandboxed/containersized process) where the pseudo process handle is invalid; a process already terminating when the check runs.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
AI-assisted analysis of andrewmd5/Borderless-Gaming@d6a541a64a (2026-09-15).
Data as JSON: /api/errors/fea237d307f0e5c7.
Report an issue: GitHub.
Appendix: source
Thrown at BorderlessGaming.Logic/Windows/Uac.cs:110
/// in that, when UAC is turned off, elevation type always returns
/// TokenElevationTypeDefault even though the process is elevated (Integrity
/// Level == High). In other words, it is not safe to say if the process is
/// elevated based on elevation type. Instead, we should use TokenElevation.
/// </remarks>
public static bool IsProcessElevated()
{
bool fIsElevated = false;
SafeTokenHandle hToken = null;
int cbTokenElevation = 0;
IntPtr pTokenElevation = IntPtr.Zero;
try
{
// Open the access token of the current process with TOKEN_QUERY.
if (!NativeMethods.OpenProcessToken(Process.GetCurrentProcess().Handle,
NativeMethods.TOKEN_QUERY, out hToken))
{
throw new Win32Exception();
}
// Allocate a buffer for the elevation information.
cbTokenElevation = Marshal.SizeOf(typeof(TOKEN_ELEVATION));
pTokenElevation = Marshal.AllocHGlobal(cbTokenElevation);
if (pTokenElevation == IntPtr.Zero)
{
throw new Win32Exception();
}
// Retrieve token elevation information.
if (!NativeMethods.GetTokenInformation(hToken,
TOKEN_INFORMATION_CLASS.TokenElevation, pTokenElevation,
cbTokenElevation, out cbTokenElevation))
{
// When the process is run on operating systems prior to Windows
// Vista, GetTokenInformation returns false with the error code
// ERROR_INVALID_PARAMETER because TokenElevation is not supported View on GitHub (pinned to d6a541a64a)