{"record":{"id":"893578790f3e6189","repo":"java-native-access/jna","slug":"win32exception-from-native-getlasterror-after-kernel32util","errorCode":null,"errorMessage":"Win32Exception from native GetLastError after GetPrivateProfileSectionNames returned 0","messagePattern":"Win32Exception from native GetLastError after GetPrivateProfileSectionNames returned 0","errorType":"error_code","errorClass":"Win32Exception","httpStatus":null,"severity":"error","filePath":"contrib/platform/src/com/sun/jna/platform/win32/Kernel32Util.java","lineNumber":816,"sourceCode":"        }\n        return new String(buffer).split(\"\\0\");\n    }\n\n    /**\n     * Retrieves the names of all sections in an initialization file.\n     * <p>\n     * This operation is atomic; no updates to the initialization file are allowed while this method is executed.\n     * </p>\n     *\n     * @param fileName\n     *            The name of the initialization file. If this parameter is {@code NULL}, the function searches the Win.ini file. If this parameter does not\n     *            contain a full path to the file, the system searches for the file in the Windows directory.\n     * @return the section names associated with the named file.\n     */\n    public static final String[] getPrivateProfileSectionNames(final String fileName) {\n        final char buffer[] = new char[65536]; // Maximum INI file size according to MSDN (http://support.microsoft.com/kb/78346)\n        if (Kernel32.INSTANCE.GetPrivateProfileSectionNames(buffer, new DWORD(buffer.length), fileName).intValue() == 0) {\n            throw new Win32Exception(Kernel32.INSTANCE.GetLastError());\n        }\n        return new String(buffer).split(\"\\0\");\n    }\n\n    /**\n     * @param appName\n     *            The name of the section in which data is written. This section name is typically the name of the calling application.\n     * @param strings\n     *            The new key names and associated values that are to be written to the named section. Each entry must be of the form {@code key=value}.\n     * @param fileName\n     *            The name of the initialization file. If this parameter does not contain a full path for the file, the function searches the Windows directory\n     *            for the file. If the file does not exist and lpFileName does not contain a full path, the function creates the file in the Windows directory.\n     */\n    public static final void writePrivateProfileSection(final String appName, final String[] strings, final String fileName) {\n        final StringBuilder buffer = new StringBuilder();\n        for (final String string : strings)\n            buffer.append(string).append('\\0');\n        buffer.append('\\0');","sourceCodeStart":798,"sourceCodeEnd":834,"githubUrl":"https://github.com/java-native-access/jna/blob/d036ad9781adad4b66693e8fa7098e4ac665e0a3/contrib/platform/src/com/sun/jna/platform/win32/Kernel32Util.java#L798-L834","documentation":"getPrivateProfileSectionNames enumerates all section names in an INI file via GetPrivateProfileSectionNames into a 65536-char buffer. A return of 0 means the enumeration failed, and the wrapper throws Win32Exception carrying the native GetLastError code. Unlike getPrivateProfileSection, there is no empty-result path here: 0 always indicates failure per the API contract.","triggerScenarios":"Calling Kernel32Util.getPrivateProfileSectionNames(fileName) when GetPrivateProfileSectionNames returns 0 — the INI file does not exist, the path is invalid, the buffer is too small for files larger than 64KB, or the file cannot be opened by the calling process.","commonSituations":"INI file missing after deployment or renamed; UNC/network path inaccessible due to credentials; an INI larger than the 64KB maximum MSDN documents; typos in the file path; file locked by another process with exclusive access.","solutions":["Check the INI file exists and is readable (absolute path) before calling.","Catch Win32Exception and map its error code (ERROR_FILE_NOT_FOUND, ERROR_PATH_NOT_FOUND) to user-facing messages.","Keep the INI under 64KB or split it; the fixed 65536-char buffer cannot grow.","Fall back to parsing the file manually (e.g. IniEditor or hand-rolled reader) if the native call repeatedly fails."],"exampleFix":"// before\nString[] sections = Kernel32Util.getPrivateProfileSectionNames(\"app.ini\");\n\n// after\nPath ini = Paths.get(\"app.ini\").toAbsolutePath();\nif (!Files.isReadable(ini)) {\n    throw new FileNotFoundException(\"Cannot read INI: \" + ini);\n}\nString[] sections;\ntry {\n    sections = Kernel32Util.getPrivateProfileSectionNames(ini.toString());\n} catch (Win32Exception e) {\n    LOG.warn(\"Section enumeration failed (code \" + e.getErrorCode() + \")\", e);\n    sections = new String[0];\n}","handlingStrategy":"try-catch","validationCode":"Path ini = Paths.get(fileName).toAbsolutePath();\nif (!Files.isReadable(ini)) {\n    throw new FileNotFoundException(ini.toString());\n}","typeGuard":null,"tryCatchPattern":"try {\n    return Kernel32Util.getPrivateProfileSectionNames(fileName);\n} catch (Win32Exception e) {\n    LOG.warn(\"INI section enum failed: \" + e.getErrorCode());\n    return new String[0];\n}","preventionTips":["Use absolute, verified paths.","Keep INI files under the 64KB documented maximum.","Treat missing files as empty results if that is acceptable in your domain.","Check file locks if the file is shared with other processes."],"tags":["win32","ini","file-read","jna"],"backgroundTag":"file-read-failed","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"}