{"record":{"id":"ac05d6d468e81ab6","repo":"java-native-access/jna","slug":"win32exception-from-native-getlasterror-after-openprocess","errorCode":null,"errorMessage":"Win32Exception from native GetLastError after OpenProcess failed","messagePattern":"Win32Exception from native GetLastError after OpenProcess failed","errorType":"error_code","errorClass":"Win32Exception","httpStatus":null,"severity":"error","filePath":"contrib/platform/src/com/sun/jna/platform/win32/Kernel32Util.java","lineNumber":931,"sourceCode":"     * This function retrieves the full path of the executable file of a given process identifier.\n     *\n     * @param pid\n     *          Identifier for the running process\n     * @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(int pid, int dwFlags) {\n        HANDLE hProcess = null;\n        Win32Exception we = null;\n\n        try {\n            hProcess = Kernel32.INSTANCE.OpenProcess(WinNT.PROCESS_QUERY_INFORMATION | WinNT.PROCESS_VM_READ, false, pid);\n            if (hProcess == null) {\n                throw new Win32Exception(Kernel32.INSTANCE.GetLastError());\n            }\n            return QueryFullProcessImageName(hProcess, dwFlags);\n        } catch (final Win32Exception e) {\n            throw we = e; // re-throw to avoid return value!\n        } finally {\n            cleanUp(hProcess, we);\n        }\n    }\n\n    /**\n     *\n     * This function retrieves the full path of the executable file of a given process.\n     *\n     * @param hProcess\n     *          Handle for the running process\n     * @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.","sourceCodeStart":913,"sourceCodeEnd":949,"githubUrl":"https://github.com/java-native-access/jna/blob/d036ad9781adad4b66693e8fa7098e4ac665e0a3/contrib/platform/src/com/sun/jna/platform/win32/Kernel32Util.java#L913-L949","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nString name = Kernel32Util.QueryFullProcessImageName(pid, 0); // throws for System PIDs\n\n// after\nString name;\ntry {\n    name = Kernel32Util.QueryFullProcessImageName(pid, 0);\n} catch (Win32Exception e) {\n    if (e.getErrorCode() == WinError.ERROR_ACCESS_DENIED) {\n        name = \"<access denied>\"; // skip protected process\n    } else {\n        throw e;\n    }\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    return Kernel32Util.QueryFullProcessImageName(pid, 0);\n} catch (Win32Exception e) {\n    if (e.getErrorCode() == WinError.ERROR_ACCESS_DENIED\n            || e.getErrorCode() == WinError.ERROR_INVALID_PARAMETER) {\n        return \"<unavailable>\"; // protected or exited process\n    }\n    throw e;\n}","preventionTips":["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."],"tags":["win32","process","permissions","jna"],"backgroundTag":"permission-denied","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"}