{"record":{"id":"d4fb1ef4d80c2625","repo":"java-native-access/jna","slug":"win32exception-from-native-getlasterror-after-d4fb1e","errorCode":null,"errorMessage":"Win32Exception from native GetLastError after CreateToolhelp32Snapshot returned null","messagePattern":"Win32Exception from native GetLastError after CreateToolhelp32Snapshot returned null","errorType":"error_code","errorClass":"Win32Exception","httpStatus":null,"severity":"error","filePath":"contrib/platform/src/com/sun/jna/platform/win32/Kernel32Util.java","lineNumber":1172,"sourceCode":"        }\n\n        if (err != null) {\n            throw err;\n        }\n        return result;\n    }\n\n    /**\n     * Returns all the executable modules for a given process ID.<br>\n     *\n     * @param processID\n     *            The process ID to get executable modules for\n     * @return All the modules in the process.\n     */\n    public static List<Tlhelp32.MODULEENTRY32W> getModules(int processID) {\n        HANDLE snapshot = Kernel32.INSTANCE.CreateToolhelp32Snapshot(Tlhelp32.TH32CS_SNAPMODULE, new DWORD(processID));\n        if (snapshot == null) {\n            throw new Win32Exception(Kernel32.INSTANCE.GetLastError());\n        }\n\n        Win32Exception we = null;\n        try {\n            Tlhelp32.MODULEENTRY32W first = new Tlhelp32.MODULEENTRY32W();\n\n            if (!Kernel32.INSTANCE.Module32FirstW(snapshot, first)) {\n                throw new Win32Exception(Kernel32.INSTANCE.GetLastError());\n            }\n\n            List<Tlhelp32.MODULEENTRY32W> modules = new ArrayList<>();\n            modules.add(first);\n\n            Tlhelp32.MODULEENTRY32W next = new Tlhelp32.MODULEENTRY32W();\n            while (Kernel32.INSTANCE.Module32NextW(snapshot, next)) {\n                modules.add(next);\n                next = new Tlhelp32.MODULEENTRY32W();\n            }","sourceCodeStart":1154,"sourceCodeEnd":1190,"githubUrl":"https://github.com/java-native-access/jna/blob/d036ad9781adad4b66693e8fa7098e4ac665e0a3/contrib/platform/src/com/sun/jna/platform/win32/Kernel32Util.java#L1154-L1190","documentation":"Kernel32Util.getModules throws this Win32Exception when Kernel32.INSTANCE.CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, processID) returns null. GetLastError carries the native reason — commonly ERROR_ACCESS_DENIED (5) for protected processes, or ERROR_INVALID_PARAMETER (87) for a nonexistent process ID.","triggerScenarios":"Calling Kernel32Util.getModules(processID) with a PID that does not exist, a system/protected process (e.g. services running as SYSTEM, PPL processes), or insufficient privileges of the calling process for TH32CS_SNAPMODULE.","commonSituations":"Enumerating modules of another user's process without elevation, snapshotting a PID that already exited (race between lookup and snapshot), listing modules of antivirus/PPL-protected processes.","solutions":["Validate the PID is alive before snapshotting (e.g. via Kernel32 OpenProcess or tasklist)","Run the caller elevated (Administrator) when targeting processes from other sessions/users","Catch Win32Exception and check errorCode: 5 = need elevation, 87 = invalid PID","Retry once on transient snapshot failures if the PID is expected to exist"],"exampleFix":"// before\nList<Tlhelp32.MODULEENTRY32W> mods = Kernel32Util.getModules(pid);\n// after\ntry {\n    List<Tlhelp32.MODULEENTRY32W> mods = Kernel32Util.getModules(pid);\n} catch (Win32Exception e) {\n    if (e.getErrorCode().intValue() == WinError.ERROR_ACCESS_DENIED) {\n        throw new IllegalStateException(\"Run elevated to inspect PID \" + pid, e);\n    }\n    throw e;\n}","handlingStrategy":"try-catch","validationCode":"// Java: check PID liveness before snapshotting\nHANDLE proc = Kernel32.INSTANCE.OpenProcess(WinNT.PROCESS_QUERY_LIMITED_INFORMATION, false, new DWORD(pid));\nif (proc == null) throw new Win32Exception(Kernel32.INSTANCE.GetLastError()); // PID dead or access denied\nKernel32.INSTANCE.CloseHandle(proc);","typeGuard":"boolean pidAlive(int pid) {\n    HANDLE p = Kernel32.INSTANCE.OpenProcess(WinNT.PROCESS_QUERY_LIMITED_INFORMATION, false, new DWORD(pid));\n    if (p == null) return false;\n    Kernel32.INSTANCE.CloseHandle(p);\n    return true;\n}","tryCatchPattern":"try {\n    List<Tlhelp32.MODULEENTRY32W> mods = Kernel32Util.getModules(pid);\n} catch (Win32Exception e) {\n    if (e.getErrorCode().intValue() == WinError.ERROR_ACCESS_DENIED) {\n        throw new IllegalStateException(\"Elevation required for PID \" + pid, e);\n    }\n    if (e.getErrorCode().intValue() == WinError.ERROR_INVALID_PARAMETER) {\n        return Collections.emptyList(); // process gone\n    }\n    throw e;\n}","preventionTips":["Verify the PID exists immediately before snapshotting","Run elevated when inspecting processes from other users/sessions","Expect access denial for PPL/protected processes and handle it explicitly","Treat missing-PID (87) as an expected outcome in process-watch code"],"tags":["win32","jni","native","processes","privileges"],"backgroundTag":"insufficient-permissions","analyzedSha":"d036ad9781adad4b66693e8fa7098e4ac665e0a3","analyzedAt":"2026-09-12T06:50:59.239Z","contentChangedAt":"2026-09-12T06:50:59.239Z","schemaVersion":2},"datasetVersion":"2026-09-19T12:17:13.211Z"}