java-native-access/jna · error · Win32Exception
Win32Exception from native GetLastError after QueryFullProce
Error message
Win32Exception from native GetLastError after QueryFullProcessImageName retry loop exhausted
What it means
QueryFullProcessImageName(HANDLE, dwFlags) grows its name buffer by 1024 chars in a loop while the API fails with ERROR_INSUFFICIENT_BUFFER. Once the loop exits for any other failure, the wrapper throws Win32Exception with the current GetLastError code. This means the buffer-size path was exhausted by a different error — typically the process handle is no longer valid or access was revoked.
Source
Thrown at contrib/platform/src/com/sun/jna/platform/win32/Kernel32Util.java:965
* @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(HANDLE hProcess, int dwFlags) {
int size = WinDef.MAX_PATH; // Start with MAX_PATH, then increment with 1024 each iteration
IntByReference lpdwSize = new IntByReference();
do {
char[] lpExeName = new char[size];
lpdwSize.setValue(size);
if (Kernel32.INSTANCE.QueryFullProcessImageName(hProcess, dwFlags, lpExeName, lpdwSize)) {
return new String(lpExeName, 0, lpdwSize.getValue());
}
size += 1024;
} while (Kernel32.INSTANCE.GetLastError() == Kernel32.ERROR_INSUFFICIENT_BUFFER);
throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
}
/**
* Gets the specified resource out of the specified executable file
*
* @param path
* The path to the executable file
* @param type
* The type of the resource (either a type name or type ID is
* allowed)
* @param name
* The name or ID of the resource
* @return The resource bytes, or null if no such resource exists.
* @throws IllegalStateException if the call to LockResource fails
*/
public static byte[] getResource(String path, String type, String name) {
HMODULE target = Kernel32.INSTANCE.LoadLibraryEx(path, null, Kernel32.LOAD_LIBRARY_AS_DATAFILE);
View on GitHub (pinned to d036ad9781)
Solutions
- Re-open the process handle and retry once — the target may have exited between calls.
- Check Win32Exception.getErrorCode(): ERROR_INVALID_HANDLE/ERROR_ACCESS_DENIED means retrying with a bigger buffer will not help.
- Skip failed PIDs in bulk enumeration instead of aborting the whole scan.
- Run with sufficient privileges (elevated / SeDebugPrivilege) if access-denied errors dominate.
Example fix
// before
String name = Kernel32Util.QueryFullProcessImageName(hProcess, 0);
// after
String name;
try {
name = Kernel32Util.QueryFullProcessImageName(hProcess, 0);
} catch (Win32Exception e) {
if (e.getErrorCode() == WinError.ERROR_INVALID_HANDLE) {
name = null; // process exited; skip
} else {
throw e;
}
} Defensive patterns
Strategy: try-catch
Try / catch
try {
return Kernel32Util.QueryFullProcessImageName(hProcess, 0);
} catch (Win32Exception e) {
if (e.getErrorCode() == WinError.ERROR_INVALID_HANDLE) {
return null; // process exited
}
throw e;
} Prevention
- Treat every enumerated process as possibly already dead; null-check results.
- Re-open handles rather than reusing them across long scans.
- Check error code before retrying with larger buffers — only ERROR_INSUFFICIENT_BUFFER benefits.
- Run with adequate privileges for protected processes.
When it happens
Trigger: The do/while retry loop ends because GetLastError != ERROR_INSUFFICIENT_BUFFER — e.g. ERROR_ACCESS_DENIED on a protected process, ERROR_INVALID_HANDLE because the process exited and its handle became stale, or an unexpected error with a full buffer (name longer than the loop's growth pattern under unusual conditions).
Common situations: Short-lived processes dying mid-query; protected processes (PPL) denying name queries even with a handle; enumerating many processes where some vanish between OpenProcess and the name query.
Related errors
- Win32Exception from native GetLastError after OpenProcess fa
- LookupAccountNameW was expected to fail with ERROR_INSUFFICI
- Expected GetTokenInformation to fail with ERROR_INSUFFICIENT
- Failed to find privilege "{privilege}" - {GetLastError}
- Win32Exception from native GetLastError after GetPrivateProf
AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12).
Data as JSON: /api/errors/eb80063bed35b498.
Report an issue: GitHub.