java-native-access/jna · error · Win32Exception

Win32Exception from native GetLastError after LoadLibraryEx

Error message

Win32Exception from native GetLastError after LoadLibraryEx failed

What it means

getResource(path, type, name) extracts an embedded resource from an executable/DLL by loading it with LoadLibraryEx using LOAD_LIBRARY_AS_DATAFILE. If LoadLibraryEx returns null, the wrapper throws Win32Exception with the native GetLastError code — typically ERROR_MOD_NOT_FOUND (file missing or its dependencies unreadable) or ERROR_BAD_EXE_FORMAT (not a valid PE file / 32-vs-64-bit mismatch).

Source

Thrown at contrib/platform/src/com/sun/jna/platform/win32/Kernel32Util.java:985

    /**
     * Gets the specified resource out of the specified executable file
     *
     * @param path
     *            The path to the executable file
     * @param type
     *            The type of the resource (either a type name or type ID is
     *            allowed)
     * @param name
     *            The name or ID of the resource
     * @return The resource bytes, or null if no such resource exists.
     * @throws IllegalStateException if the call to LockResource fails
     */
    public static byte[] getResource(String path, String type, String name) {
        HMODULE target = Kernel32.INSTANCE.LoadLibraryEx(path, null, Kernel32.LOAD_LIBRARY_AS_DATAFILE);

        if (target == null) {
            throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
        }

        Win32Exception err = null;
        Pointer start = null;
        int length = 0;
        byte[] results = null;
        try {
            Pointer t = null;
            try {
                t = new Pointer(Long.parseLong(type));
            } catch (NumberFormatException e) {
                t = new Memory(Native.WCHAR_SIZE * (type.length() + 1));
                t.setWideString(0, type);
            }

            Pointer n = null;
            try {
                n = new Pointer(Long.parseLong(name));

View on GitHub (pinned to d036ad9781)

Solutions

  1. Verify the file exists and is a native PE (check MZ header) before calling: new File(path).isFile().
  2. Resolve the path to an absolute path to avoid dependence on the process working directory.
  3. Inspect Win32Exception.getErrorCode(): 126 (ERROR_MOD_NOT_FOUND) = missing file, 193 (ERROR_BAD_EXE_FORMAT) = wrong architecture/format.
  4. Catch Win32Exception and provide a fallback resource lookup or a clear user-facing message.

Example fix

// before
byte[] icon = Kernel32Util.getResource("notepad.exe", "RT_GROUP_ICON", "APP");

// after
Path exe = Paths.get("C:\\Windows\\notepad.exe").toAbsolutePath();
if (!Files.isRegularFile(exe)) {
    throw new FileNotFoundException(exe.toString());
}
byte[] icon;
try {
    icon = Kernel32Util.getResource(exe.toString(), "RT_GROUP_ICON", "APP");
} catch (Win32Exception e) {
    throw new IOException("Cannot load resources from " + exe + " (code " + e.getErrorCode() + ")", e);
}
Defensive patterns

Strategy: validation

Validate before calling

Path p = Paths.get(path).toAbsolutePath();
if (!Files.isRegularFile(p)) {
    throw new FileNotFoundException(p.toString());
}
try (FileChannel ch = FileChannel.open(p, StandardOpenOption.READ)) {
    byte[] hdr = new byte[2];
    ch.read(ByteBuffer.wrap(hdr));
    if (hdr[0] != 'M' || hdr[1] != 'Z') {
        throw new IOException("Not a PE file: " + p);
    }
}

Try / catch

try {
    return Kernel32Util.getResource(path, type, name);
} catch (Win32Exception e) {
    throw new IOException("LoadLibraryEx failed for " + path + " (code " + e.getErrorCode() + ")", e);
}

Prevention

When it happens

Trigger: Calling Kernel32Util.getResource(path, type, name) when LoadLibraryEx(path, null, LOAD_LIBRARY_AS_DATAFILE) returns null — the file path does not exist, the file is not a valid PE image, the path is a resource DLL for the wrong architecture, or the file cannot be opened due to permissions/locking.

Common situations: Typo'd or relative DLL path resolved against the wrong working directory; attempting to read resources from a .NET assembly or script that is not a native PE; antivirus quarantining/locking the file; extracting icons/strings from an executable that was since updated or removed.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12). Data as JSON: /api/errors/cb2ebbdcf3038d32. Report an issue: GitHub.