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

  1. Re-open the process handle and retry once — the target may have exited between calls.
  2. Check Win32Exception.getErrorCode(): ERROR_INVALID_HANDLE/ERROR_ACCESS_DENIED means retrying with a bigger buffer will not help.
  3. Skip failed PIDs in bulk enumeration instead of aborting the whole scan.
  4. 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

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


AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12). Data as JSON: /api/errors/eb80063bed35b498. Report an issue: GitHub.