{"record":{"id":"aed2ac514d927127","repo":"java-native-access/jna","slug":"win32exception-from-getlasterror-after","errorCode":null,"errorMessage":"Win32Exception from GetLastError after GetVolumePathNamesForVolumeName failed (not ERROR_MORE_DATA)","messagePattern":"Win32Exception from GetLastError after GetVolumePathNamesForVolumeName failed \\(not ERROR_MORE_DATA\\)","errorType":"error_code","errorClass":"Win32Exception","httpStatus":null,"severity":"error","filePath":"contrib/platform/src/com/sun/jna/platform/win32/Kernel32Util.java","lineNumber":870,"sourceCode":"        }\n\n        return Native.toStringList(lpTargetPath, 0, dwSize);\n    }\n\n    /**\n     * Invokes and parses the result of {@link Kernel32#GetVolumePathNamesForVolumeName(String, char[], int, IntByReference)}\n     * @param lpszVolumeName The volume name\n     * @return The parsed result\n     * @throws Win32Exception If failed to retrieve the required information\n     */\n    public static final List<String> getVolumePathNamesForVolumeName(String lpszVolumeName) {\n        char[] lpszVolumePathNames = new char[WinDef.MAX_PATH + 1];\n        IntByReference lpcchReturnLength = new IntByReference();\n\n        if (!Kernel32.INSTANCE.GetVolumePathNamesForVolumeName(lpszVolumeName, lpszVolumePathNames, lpszVolumePathNames.length, lpcchReturnLength)) {\n            int hr = Kernel32.INSTANCE.GetLastError();\n            if (hr != WinError.ERROR_MORE_DATA) {\n                throw new Win32Exception(hr);\n            }\n\n            int required = lpcchReturnLength.getValue();\n            lpszVolumePathNames = new char[required];\n            // this time we MUST succeed\n            if (!Kernel32.INSTANCE.GetVolumePathNamesForVolumeName(lpszVolumeName, lpszVolumePathNames, lpszVolumePathNames.length, lpcchReturnLength)) {\n                throw new Win32Exception(Kernel32.INSTANCE.GetLastError());\n            }\n        }\n\n        int bufSize = lpcchReturnLength.getValue();\n        return Native.toStringList(lpszVolumePathNames, 0, bufSize);\n    }\n\n    // prefix and suffix of a volume GUID path\n    public static final String VOLUME_GUID_PATH_PREFIX = \"\\\\\\\\?\\\\Volume{\";\n    public static final String VOLUME_GUID_PATH_SUFFIX = \"}\\\\\";\n","sourceCodeStart":852,"sourceCodeEnd":888,"githubUrl":"https://github.com/java-native-access/jna/blob/d036ad9781adad4b66693e8fa7098e4ac665e0a3/contrib/platform/src/com/sun/jna/platform/win32/Kernel32Util.java#L852-L888","documentation":"getVolumePathNamesForVolumeName maps a volume GUID (\\\\?\\Volume{...}\\) to its mount point paths using GetVolumePathNamesForVolumeName. The wrapper first calls with a MAX_PATH+1 buffer; if the call fails with any error other than ERROR_MORE_DATA (meaning 'buffer too small, retry'), it throws Win32Exception with the native GetLastError code. This is a hard failure of the volume lookup, not the expected grow-and-retry path.","triggerScenarios":"Calling Kernel32Util.getVolumePathNamesForVolumeName(volumeGUID) when the first GetVolumePathNamesForVolumeName call returns FALSE with GetLastError != ERROR_MORE_DATA — the volume GUID string is malformed, the volume does not exist or was unmounted, or access to the volume manager is denied.","commonSituations":"Passing a drive letter (\"C:\\\") instead of a volume GUID path; GUID string from a stale registry entry or old enumeration after the volume was removed; USB/removable volume unplugged; running without privileges to query volume information.","solutions":["Ensure the input is a full volume GUID path of the form \\\\?\\Volume{GUID}\\ — use Kernel32Util.extractVolumeGUID/PathByGuid to validate or build it.","Re-enumerate volumes via Kernel32.INSTANCE.FindFirstVolume/FindNextVolume instead of trusting cached GUIDs.","Catch Win32Exception and check for ERROR_FILE_NOT_FOUND/ERROR_INVALID_NAME to distinguish missing vs malformed input.","Run under an account with volume query privileges if ERROR_ACCESS_DENIED is returned."],"exampleFix":"// before\nString[] paths = Kernel32Util.getVolumePathNamesForVolumeName(\"C:\\\\\"); // wrong: not a GUID path\n\n// after\nString guidPath = \"\\\\\\\\?\\\\Volume{abcd1234-...}\\\\\";\ntry {\n    String[] paths = Kernel32Util.getVolumePathNamesForVolumeName(guidPath);\n} catch (Win32Exception e) {\n    if (e.getErrorCode() == WinError.ERROR_FILE_NOT_FOUND) {\n        paths = new String[0]; // volume no longer present\n    } else {\n        throw e;\n    }\n}","handlingStrategy":"validation","validationCode":"if (volumeGUIDPath == null\n        || !volumeGUIDPath.matches(\"^\\\\\\\\\\\\?\\\\\\\\Volume\\\\{[0-9a-fA-F\\\\-]+\\\\}\\\\\\\\$\")) {\n    throw new IllegalArgumentException(\"Not a volume GUID path: \" + volumeGUIDPath);\n}","typeGuard":"static boolean isVolumeGuidPath(String s) {\n    return s != null && s.matches(\"^\\\\\\\\\\\\?\\\\\\\\Volume\\\\{[0-9a-fA-F\\\\-]+\\\\}\\\\\\\\$\");\n}","tryCatchPattern":"try {\n    return Kernel32Util.getVolumePathNamesForVolumeName(guid);\n} catch (Win32Exception e) {\n    if (e.getErrorCode() == WinError.ERROR_FILE_NOT_FOUND) {\n        return new String[0];\n    }\n    throw e;\n}","preventionTips":["Only pass paths obtained from FindFirstVolume/FindNextVolume.","Re-enumerate volumes rather than caching GUIDs across sessions.","Validate the \\\\?\\Volume{...}\\ format before calling.","Handle removable volumes disappearing at any moment."],"tags":["win32","volume","jna"],"backgroundTag":"resource-not-found","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"}