{"record":{"id":"eb80063bed35b498","repo":"java-native-access/jna","slug":"win32exception-from-native-getlasterror-after-eb8006","errorCode":null,"errorMessage":"Win32Exception from native GetLastError after QueryFullProcessImageName retry loop exhausted","messagePattern":"Win32Exception from native GetLastError after QueryFullProcessImageName retry loop exhausted","errorType":"error_code","errorClass":"Win32Exception","httpStatus":null,"severity":"error","filePath":"contrib/platform/src/com/sun/jna/platform/win32/Kernel32Util.java","lineNumber":965,"sourceCode":"     * @param dwFlags\n     *          0 - The name should use the Win32 path format.\n     *          1(WinNT.PROCESS_NAME_NATIVE) - The name should use the native system path format.\n     *\n     * @return the full path of the process's executable file of null if failed. To get extended error information,\n     *         call GetLastError.\n     */\n    public static final String QueryFullProcessImageName(HANDLE hProcess, int dwFlags) {\n        int size = WinDef.MAX_PATH; // Start with MAX_PATH, then increment with 1024 each iteration\n        IntByReference lpdwSize = new IntByReference();\n        do {\n            char[] lpExeName = new char[size];\n            lpdwSize.setValue(size);\n            if (Kernel32.INSTANCE.QueryFullProcessImageName(hProcess, dwFlags, lpExeName, lpdwSize)) {\n                return new String(lpExeName, 0, lpdwSize.getValue());\n            }\n            size += 1024;\n        } while (Kernel32.INSTANCE.GetLastError() == Kernel32.ERROR_INSUFFICIENT_BUFFER);\n        throw new Win32Exception(Kernel32.INSTANCE.GetLastError());\n    }\n\n    /**\n     * Gets the specified resource out of the specified executable file\n     *\n     * @param path\n     *            The path to the executable file\n     * @param type\n     *            The type of the resource (either a type name or type ID is\n     *            allowed)\n     * @param name\n     *            The name or ID of the resource\n     * @return The resource bytes, or null if no such resource exists.\n     * @throws IllegalStateException if the call to LockResource fails\n     */\n    public static byte[] getResource(String path, String type, String name) {\n        HMODULE target = Kernel32.INSTANCE.LoadLibraryEx(path, null, Kernel32.LOAD_LIBRARY_AS_DATAFILE);\n","sourceCodeStart":947,"sourceCodeEnd":983,"githubUrl":"https://github.com/java-native-access/jna/blob/d036ad9781adad4b66693e8fa7098e4ac665e0a3/contrib/platform/src/com/sun/jna/platform/win32/Kernel32Util.java#L947-L983","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"// before\nString name = Kernel32Util.QueryFullProcessImageName(hProcess, 0);\n\n// after\nString name;\ntry {\n    name = Kernel32Util.QueryFullProcessImageName(hProcess, 0);\n} catch (Win32Exception e) {\n    if (e.getErrorCode() == WinError.ERROR_INVALID_HANDLE) {\n        name = null; // process exited; skip\n    } else {\n        throw e;\n    }\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    return Kernel32Util.QueryFullProcessImageName(hProcess, 0);\n} catch (Win32Exception e) {\n    if (e.getErrorCode() == WinError.ERROR_INVALID_HANDLE) {\n        return null; // process exited\n    }\n    throw e;\n}","preventionTips":["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."],"tags":["win32","process","jna"],"backgroundTag":"win32-native-error","analyzedSha":"d036ad9781adad4b66693e8fa7098e4ac665e0a3","analyzedAt":"2026-09-12T06:50:59.239Z","contentChangedAt":"2026-09-12T06:50:59.239Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}