{"record":{"id":"1118e1264d90860e","repo":"java-native-access/jna","slug":"win32exception-kernel32-instance-getlasterror-netapi32util","errorCode":null,"errorMessage":"Win32Exception(Kernel32.INSTANCE.GetLastError())","messagePattern":"Win32Exception\\(Kernel32\\.INSTANCE\\.GetLastError\\(\\)\\)","errorType":"error_code","errorClass":"Win32Exception","httpStatus":null,"severity":"error","filePath":"contrib/platform/src/com/sun/jna/platform/win32/Netapi32Util.java","lineNumber":128,"sourceCode":"     * @param serverName\n     *     Specifies the DNS or NetBIOS name of the remote server on which the function is\n     *     to execute.\n     * @param domainName\n     *     Specifies the name of the domain.\n     * @return\n     *  Name of the primary domain controller.\n     */\n    public static String getDCName(String serverName, String domainName) {\n        PointerByReference bufptr = new PointerByReference();\n        try {\n            int rc = Netapi32.INSTANCE.NetGetDCName(serverName, domainName, bufptr);\n            if (LMErr.NERR_Success != rc) {\n                throw new Win32Exception(rc);\n            }\n            return bufptr.getValue().getWideString(0);\n        } finally {\n            if (W32Errors.ERROR_SUCCESS != Netapi32.INSTANCE.NetApiBufferFree(bufptr.getValue())) {\n                throw new Win32Exception(Kernel32.INSTANCE.GetLastError());\n            }\n        }\n    }\n\n    /**\n     * Return the domain/workgroup join status for a computer.\n     * @return Join status.\n     */\n    public static int getJoinStatus() {\n        return getJoinStatus(null);\n    }\n\n    /**\n     * Return the domain/workgroup join status for a computer.\n     * @param computerName Computer name.\n     * @return Join status.\n     */\n    public static int getJoinStatus(String computerName) {","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/java-native-access/jna/blob/d036ad9781adad4b66693e8fa7098e4ac665e0a3/contrib/platform/src/com/sun/jna/platform/win32/Netapi32Util.java#L110-L146","documentation":"After calling NetGetDCName, getDCName frees the native buffer with NetApiBufferFree in a finally block. If the free call itself fails, the resulting GetLastError() code is wrapped in a Win32Exception and thrown. Note this can mask the original return value or any in-flight exception from the try block.","triggerScenarios":"NetApiBufferFree returns non-ERROR_SUCCESS while cleaning up the DC-name buffer — e.g. bufptr.getValue() is NULL because NetGetDCName failed and never allocated a buffer, or the pointer is already invalid.","commonSituations":"getDCName failing (e.g. no DC found) so the finally block frees a NULL/invalid pointer and throws a second, confusing exception that hides the real cause.","solutions":["Treat this exception as secondary: the real failure is usually in NetGetDCName; capture and log both errors.","Guard the finally block: only free when bufptr.getValue() != Pointer.NULL.","Upgrade JNA — newer versions harden these cleanup paths against NULL buffers.","If it persists, check for heap/native memory corruption elsewhere in the process."],"exampleFix":"// before\n} finally {\n    if (W32Errors.ERROR_SUCCESS != Netapi32.INSTANCE.NetApiBufferFree(bufptr.getValue())) {\n        throw new Win32Exception(Kernel32.INSTANCE.GetLastError());\n    }\n}\n// after\n} finally {\n    if (bufptr.getValue() != Pointer.NULL\n            && W32Errors.ERROR_SUCCESS != Netapi32.INSTANCE.NetApiBufferFree(bufptr.getValue())) {\n        throw new Win32Exception(Kernel32.INSTANCE.GetLastError());\n    }\n}","handlingStrategy":"try-catch","validationCode":"// Only call getDCName when it can succeed; a failed call is what corrupts cleanup\nPointerByReference bufptr = new PointerByReference();\nint rc = Netapi32.INSTANCE.NetGetDCName(null, domain, bufptr);\nboolean ok = (rc == LMErr.NERR_Success) && bufptr.getValue() != Pointer.NULL;","typeGuard":null,"tryCatchPattern":"try {\n    return Netapi32Util.getDCName(server, domain);\n} catch (Win32Exception e) {\n    LOG.warn(\"getDCName/cleanup failed, rc=\" + e.getErrorCode());\n    return null; // treat as 'no DC available'\n}","preventionTips":["Upgrade JNA — newer releases guard the buffer-free path against NULL pointers.","Never ignore the primary getDCName failure; this cleanup error usually stems from it.","Pin a single JNA version to avoid duplicate native library loads.","If seen on successful calls, audit the process for native heap corruption."],"tags":["win32","jna","memory","native"],"backgroundTag":"win32-api-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"}