java-native-access/jna · error · Win32Exception
Win32Exception from native GetLastError after OpenProcess fa
Error message
Win32Exception from native GetLastError after OpenProcess failed
What it means
QueryFullProcessImageName(pid, dwFlags) first opens the target process with PROCESS_QUERY_INFORMATION | PROCESS_VM_READ via OpenProcess. If OpenProcess returns null (failure), the wrapper throws Win32Exception with the native GetLastError code — classically ERROR_ACCESS_DENIED for protected/system processes. The handle is cleaned up in a finally block; the exception is re-thrown after cleanup.
Source
Thrown at contrib/platform/src/com/sun/jna/platform/win32/Kernel32Util.java:931
* This function retrieves the full path of the executable file of a given process identifier.
*
* @param pid
* Identifier for the running process
* @param dwFlags
* 0 - The name should use the Win32 path format.
* 1(WinNT.PROCESS_NAME_NATIVE) - The name should use the native system path format.
*
* @return the full path of the process's executable file of null if failed. To get extended error information,
* call GetLastError.
*/
public static final String QueryFullProcessImageName(int pid, int dwFlags) {
HANDLE hProcess = null;
Win32Exception we = null;
try {
hProcess = Kernel32.INSTANCE.OpenProcess(WinNT.PROCESS_QUERY_INFORMATION | WinNT.PROCESS_VM_READ, false, pid);
if (hProcess == null) {
throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
}
return QueryFullProcessImageName(hProcess, dwFlags);
} catch (final Win32Exception e) {
throw we = e; // re-throw to avoid return value!
} finally {
cleanUp(hProcess, we);
}
}
/**
*
* This function retrieves the full path of the executable file of a given process.
*
* @param hProcess
* Handle for the running process
* @param dwFlags
* 0 - The name should use the Win32 path format.
* 1(WinNT.PROCESS_NAME_NATIVE) - The name should use the native system path format.View on GitHub (pinned to d036ad9781)
Solutions
- Check the process still exists before opening (Kernel32.INSTANCE.OpenProcess failure with ERROR_INVALID_PARAMETER means it exited).
- Run the JVM elevated or grant SeDebugPrivilege when querying other users'/system processes.
- Catch Win32Exception and skip processes returning ERROR_ACCESS_DENIED instead of failing the whole enumeration.
- Request only needed access; consider PROCESS_QUERY_LIMITED_INFORMATION (supported by the dwFlags variant) which succeeds on more processes.
Example fix
// before
String name = Kernel32Util.QueryFullProcessImageName(pid, 0); // throws for System PIDs
// after
String name;
try {
name = Kernel32Util.QueryFullProcessImageName(pid, 0);
} catch (Win32Exception e) {
if (e.getErrorCode() == WinError.ERROR_ACCESS_DENIED) {
name = "<access denied>"; // skip protected process
} else {
throw e;
}
} Defensive patterns
Strategy: try-catch
Try / catch
try {
return Kernel32Util.QueryFullProcessImageName(pid, 0);
} catch (Win32Exception e) {
if (e.getErrorCode() == WinError.ERROR_ACCESS_DENIED
|| e.getErrorCode() == WinError.ERROR_INVALID_PARAMETER) {
return "<unavailable>"; // protected or exited process
}
throw e;
} Prevention
- Skip protected/system PIDs (0, 4, System, antivirus) in enumerations.
- Run elevated or with SeDebugPrivilege when inspecting other users' processes.
- Expect PIDs to vanish between listing and opening; handle ERROR_INVALID_PARAMETER as 'gone'.
- Prefer PROCESS_QUERY_LIMITED_INFORMATION where the API variant allows.
When it happens
Trigger: Calling Kernel32Util.QueryFullProcessImageName(int pid, int dwFlags) when OpenProcess fails — the PID does not exist (ERROR_INVALID_PARAMETER), the process is a protected/system process (ERROR_ACCESS_DENIED), or the caller lacks SeDebugPrivilege and is not on the same user session.
Common situations: Enumerating all PIDs (e.g. from tasklist or ProcessHandle.allProcesses) and hitting PID 4/System or antivirus processes; process exited between listing and opening; running as a normal user while targeting another user's process; sandboxed services without debug privileges.
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.
Related errors
- Win32Exception from native GetLastError after QueryFullProce
- Win32Exception from native GetLastError after OpenThread fai
- LookupAccountNameW was expected to fail with ERROR_INSUFFICI
- Expected GetTokenInformation to fail with ERROR_INSUFFICIENT
- Failed to find privilege "{privilege}" - {GetLastError}
AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12).
Data as JSON: /api/errors/ac05d6d468e81ab6.
Report an issue: GitHub.